Repository: dr-prodigy/python-holidays

Issue:
Add NYSE years coverage
Add all financials 1950-2050 test coverage.

Discussion:
coveralls: 
[![Coverage Status](https://coveralls.io/builds/58272883/badge)](https://coveralls.io/builds/58272883)

Coverage: 99.933%. Remained the same when pulling **fac82337463d107a3eb893018e88f1f8cca1c867 on arkid15r:add-financial-tests** into **bfd8a1a95561bdf4f418846e746011dfaaf6bb2e on dr-prodigy:beta**.


Patch:
diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml
index 1bb666ba..9c9f16a1 100644
--- a/.github/workflows/ci-cd.yml
+++ b/.github/workflows/ci-cd.yml
@@ -82,7 +82,7 @@ jobs:
           make package
 
       - name: Publish Package
-        uses: pypa/gh-action-pypi-publish@v1.8.1
+        uses: pypa/gh-action-pypi-publish@v1.8.3
         with:
           user: __token__
           password: ${{ secrets.pypi_password }}
diff --git a/README.rst b/README.rst
index 888c174e..76ad7e06 100644
--- a/README.rst
+++ b/README.rst
@@ -236,7 +236,7 @@ subdivisions are available:
      - None
    * - France
      - FR
-     - Départements: Alsace-Moselle, Guadeloupe, Guyane, La Réunion, Martinique, Mayotte, **Métropole** (default), Nouvelle-Calédonie, Polynésie Française, Saint-Barthélémy, Saint-Martin, Wallis-et-Futuna
+     - Départements: Alsace-Moselle, Guadeloupe, Guyane, La Réunion, Martinique, Mayotte, Métropole, Nouvelle-Calédonie, Polynésie Française, Saint-Barthélémy, Saint-Martin, Wallis-et-Futuna
    * - Georgia
      - GE
      - None
@@ -568,6 +568,9 @@ default language code is a `ISO 639-1 code`_.
    * - Ethiopia
      - am
      - am, en_US
+   * - France
+     - fr
+     - en_US, fr, uk
    * - Georgia
      - ka
      - en_US, ka
diff --git a/holidays/countries/france.py b/holidays/countries/france.py
index e540ca13..f8c420d5 100644
--- a/holidays/countries/france.py
+++ b/holidays/countries/france.py
@@ -9,16 +9,15 @@
 #  Website: https://github.com/dr-prodigy/python-holidays
 #  License: MIT (see LICENSE file)
 
-from datetime import date
 from datetime import timedelta as td
+from gettext import gettext as tr
 
-from dateutil.easter import easter
-
-from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
+from holidays.constants import MAR, APR, MAY, JUN, JUL, SEP, OCT, NOV, DEC
 from holidays.holiday_base import HolidayBase
+from holidays.holiday_groups import ChristianHolidays, InternationalHolidays
 
 
-class France(HolidayBase):
+class France(HolidayBase, ChristianHolidays, InternationalHolidays):
     """Official French holidays.
 
     Some provinces have specific holidays, only those are included in the
@@ -34,6 +33,7 @@ class France(HolidayBase):
     """
 
     country = "FR"
+    default_language = "fr"
     subdivisions = [
         "Alsace-Moselle",
         "Guadeloupe",
@@ -49,99 +49,129 @@ class France(HolidayBase):
         "Wallis-et-Futuna",
     ]
 
-    def __init__(self, **kwargs):
-        # Default subdivision to Métropole; prov for backwards compatibility
-        if not kwargs.get("subdiv", kwargs.get("prov")):
-            kwargs["subdiv"] = "Métropole"
-        HolidayBase.__init__(self, **kwargs)
+    def __init__(self, *args, **kwargs):
+        ChristianHolidays.__init__(self)
+        InternationalHolidays.__init__(self)
+        super().__init__(*args, **kwargs)
 
     def _populate(self, year):
         super()._populate(year)
 
         # Civil holidays
-        if year > 1810:
-            self[date(year, JAN, 1)] = "Jour de l'an"
 
-        if year > 1919:
-            name = "Fête du Travail"
-            if year <= 1948:
-                name += " et de la Concorde sociale"
-            self[date(year, MAY, 1)] = name
+        if year >= 1811:
+            # New Year's Day.
+            self._add_new_years_day(tr("Jour de l'an"))
+
+        if year >= 1919:
+            self._add_labour_day(
+                # Labor Day.
+                tr("Fête du Travail")
+                if year >= 1948
+                # Labor and Social Concord Day.
+                else tr("Fête du Travail et de la Concorde sociale")
+            )
 
-        if (1953 <= year <= 1959) or year > 1981:
-            self[date(year, MAY, 8)] = "Armistice 1945"
+        if 1953 <= year <= 1959 or year >= 1982:
+            # Victory Day.
+            self._add_holiday(tr("Fête de la Victoire"), MAY, 8)
 
         if year >= 1880:
-            self[date(year, JUL, 14)] = "Fête nationale"
+            # National Day.
+            self._add_holiday(tr("Fête nationale"), JUL, 14)
 
         if year >= 1918:
-            self[date(year, NOV, 11)] = "Armistice 1918"
+            # Armistice Day.
+            self._add_holiday(tr("Armistice"), NOV, 11)
 
         # Religious holidays
-        easter_date = easter(year)
 
         if self.subdiv in {
             "Alsace-Moselle",
             "Guadeloupe",
-            "Guyane",
             "Martinique",
             "Polynésie Française",
         }:
-            self[easter_date + td(days=-2)] = "Vendredi saint"
+            # Good Friday.
+            self._add_good_friday(tr("Vendredi saint"))
 
-        if self.subdiv == "Alsace-Moselle":
-            self[date(year, DEC, 26)] = "Deuxième jour de Noël"
+        if self.subdiv == "Guadeloupe":
+            self._add_holiday(
+                # Mi-Careme.
+                tr("Mi-Carême"),
+                self._easter_sunday + td(days=-24),
+            )
 
         if year >= 1886:
-            self[easter_date + td(days=+1)] = "Lundi de Pâques"
-            self[easter_date + td(days=+50)] = "Lundi de Pentecôte"
+            # Easter Monday.
+            self._add_easter_monday(tr("Lundi de Pâques"))
+
+            if year not in {2005, 2006, 2007}:
+                # Whit Monday.
+                self._add_whit_monday(tr("Lundi de Pentecôte"))
 
         if year >= 1802:
-            self[easter_date + td(days=+39)] = "Ascension"
-            self[date(year, AUG, 15)] = "Assomption"
-            self[date(year, NOV, 1)] = "Toussaint"
+            # Ascension Day.
+            self._add_ascension_thursday(tr("Ascension"))
+            # Assumption Day.
+            self._add_assumption_of_mary_day(tr("Assomption"))
+            # All Saints' Day.
+            self._add_all_saints_day(tr("Toussaint"))
+            # Christmas Day.
+            self._add_christmas_day(tr("Noël"))
 
-            name = "Noël"
-            if self.subdiv == "Alsace-Moselle":
-                name = "Premier jour de " + name
-            self[date(year, DEC, 25)] = name
+        # Non-metropolitan holidays
 
-        # Non-metropolitan holidays (starting dates missing)
-        if self.subdiv == "Mayotte":
-            self[date(year, APR, 27)] = "Abolition de l'esclavage"
+        if self.subdiv in {"Guadeloupe", "Martinique"}:
+            # Feast of Victor Schoelcher.
+            self._add_holiday(tr("Fête de Victor Schoelcher"), JUL, 21)
 
-        if self.subdiv == "Wallis-et-Futuna":
-            self[date(year, APR, 28)] = "Saint Pierre Chanel"
+        # Abolition of slavery.
+        abolition_name = tr("Abolition de l'esclavage")
 
-        if self.subdiv == "Martinique":
-            self[date(year, MAY, 22)] = "Abolition de l'esclavage"
+        if self.subdiv == "Alsace-Moselle":
+            # Saint Stephen's Day.
+            self._add_christmas_day_two(tr("Saint Étienne"))
 
-        if self.subdiv in {"Guadeloupe", "Saint-Martin"}:
-            self[date(year, MAY, 27)] = "Abolition de l'esclavage"
+        elif self.subdiv == "Guadeloupe":
+            self._add_holiday(abolition_name, MAY, 27)
 
-        if self.subdiv == "Guyane":
-            self[date(year, JUN, 10)] = "Abolition de l'esclavage"
+        elif self.subdiv == "Guyane":
+            self._add_holiday(abolition_name, JUN, 10)
 
-        if self.subdiv == "Polynésie Française":
-            self[date(year, JUN, 29)] = "Fête de l'autonomie"
+        elif self.subdiv == "La Réunion" and year >= 1981:
+            self._add_holiday(abolition_name, DEC, 20)
 
-        if self.subdiv in {"Guadeloupe", "Martinique"}:
-            self[date(year, JUL, 21)] = "Fête Victor Schoelcher"
+        elif self.subdiv == "Martinique":
+            self._add_holiday(abolition_name, MAY, 22)
+
+        elif self.subdiv == "Mayotte":
+            self._add_holiday(abolition_name, APR, 27)
+
+        elif self.subdiv == "Nouvelle-Calédonie":
+            # Citizenship Day.
+            self._add_holiday(tr("Fête de la Citoyenneté"), SEP, 24)
 
-        if self.subdiv == "Wallis-et-Futuna":
-            self[date(year, JUL, 29)] = "Fête du Territoire"
+        elif self.subdiv == "Polynésie Française":
+            # Missionary Day.
+            self._add_holiday(tr("Arrivée de l'Évangile"), MAR, 5)
+            # Internal Autonomy Day.
+            self._add_holiday(tr("Fête de l'autonomie"), JUN, 29)
 
-        if self.subdiv == "Nouvelle-Calédonie":
-            self[date(year, SEP, 24)] = "Fête de la Citoyenneté"
+        elif self.subdiv == "Saint-Barthélémy":
+            self._add_holiday(abolition_name, OCT, 9)
 
-        if self.subdiv == "Saint-Barthélémy":
-            self[date(year, OCT, 9)] = "Abolition de l'esclavage"
+        elif self.subdiv == "Saint-Martin" and year >= 2018:
+            self._add_holiday(abolition_name, MAY, 28)
 
-        if self.subdiv == "La Réunion" and year >= 1981:
-            self[date(year, DEC, 20)] = "Abolition de l'esclavage"
+        elif self.subdiv == "Wallis-et-Futuna":
+            # Feast of Saint Peter Chanel.
+            self._add_holiday(tr("Saint Pierre Chanel"), APR, 28)
+            # Festival of the territory
+            self._add_holiday(tr("Fête du Territoire"), JUL, 29)
 
 
-# *Warning* FR is also used by dateutlis (Friday), so be careful with its use
+# *Warning* FR is also used by dateutil (Friday), so be careful with its use
 class FR(France):
     pass
 
diff --git a/holidays/countries/south_korea.py b/holidays/countries/south_korea.py
index e0d23577..df09195f 100644
--- a/holidays/countries/south_korea.py
+++ b/holidays/countries/south_korea.py
@@ -13,11 +13,8 @@
 import warnings
 from datetime import date
 from datetime import timedelta as td
-from typing import Tuple
 
-from dateutil.relativedelta import relativedelta as rd
-
-from holidays.constants import SAT, SUN, MAR, APR, MAY, JUN, JUL, AUG, OCT
+from holidays.constants import MAR, APR, MAY, JUN, JUL, AUG, OCT, SAT, SUN
 from holidays.holiday_base import HolidayBase
 from holidays.holiday_groups import ChristianHolidays, InternationalHolidays
 from holidays.holiday_groups import KoreanCalendarHolidays
@@ -56,50 +53,83 @@ class SouthKorea(
         KoreanCalendarHolidays.__init__(self)
         super().__init__(*args, **kwargs)
 
+    def _add_with_alt_holiday(
+        self,
+        hol_name: str,
+        hol_date: date,
+        add_hol: bool = True,
+        since: int = 2021,
+        include_sat: bool = True,
+    ) -> None:
+        """Add alternative holiday on first day from the date provided
+        that's not already a another holiday nor a weekend.
+
+        :param hol_name:
+           The name of the holiday.
+
+        :param hol_date:
+           The date of the holiday.
+
+        :param add_hol:
+           Add the holiday itself, not alternative only
+
+        :param since:
+           Year starting from which alt holiday should be added
+
+        :param include_sat:
+           Whether Saturday is to be considered a weekend in addition to
+           Sunday.
+        """
+        if add_hol:
+            self._add_holiday(hol_name, hol_date)
+
+        if not self.observed:
+            return None
+
+        target_weekday = {SUN}
+        if include_sat:
+            target_weekday.add(SAT)
+        if (
+            hol_date.weekday() in target_weekday
+            or len(self.get_list(hol_date)) > 1
+        ) and hol_date.year >= since:
+            hol_date += td(days=+1)
+            while hol_date.weekday() in target_weekday or hol_date in self:
+                hol_date += td(days=+1)
+            self._add_holiday("Alternative holiday of %s" % hol_name, hol_date)
+
     def _populate(self, year):
         super()._populate(year)
 
-        alt_holiday = "Alternative holiday of "
-
         # New Year's Day
         self._add_new_years_day("New Year's Day")
 
+        preceding_day = "The day preceding of %s"
+        second_day = "The second day of %s"
+
         # Lunar New Year
         name = "Lunar New Year's Day"
-        preceding_day_lunar = "The day preceding of " + name
-        second_day_lunar = "The second day of " + name
-
-        self._add_korean_new_years_eve(preceding_day_lunar)
-        self._add_korean_new_years_day(name)
-        self._add_korean_new_years_day_two(second_day_lunar)
-
-        if self.observed and year >= 2015:
-            for cur_rd, cur_name in (
-                (-1, preceding_day_lunar),
-                (0, name),
-                (+1, second_day_lunar),
-            ):
-                target_date = self._korean_new_year + td(days=cur_rd)
-                is_alt, alt_date = self.get_next_non_holiday(
-                    cur_name, target_date
-                )
-                if is_alt:
-                    self._add_holiday(alt_holiday + name, alt_date)
+        new_year_date = self._add_korean_new_years_day(name)
+        self._add_korean_new_years_eve(preceding_day % name)
+        self._add_korean_new_years_day_two(second_day % name)
+
+        for delta in (-1, 0, +1):
+            self._add_with_alt_holiday(
+                name,
+                new_year_date + td(days=delta),
+                add_hol=False,
+                since=2015,
+                include_sat=False,
+            )
 
         # Independence Movement Day
-        name = "Independence Movement Day"
-        mar_1 = self._add_holiday(name, MAR, 1)
-
-        if self.observed and year >= 2021:
-            is_alt, alt_date = self.get_next_non_holiday(
-                name, mar_1, include_sat=True
-            )
-            if is_alt:
-                self._add_holiday(alt_holiday + name, alt_date)
+        self._add_with_alt_holiday(
+            "Independence Movement Day", date(year, MAR, 1)
+        )
 
         # Tree Planting Day
         # removed from holiday since 2006
-        if self.observed and 1949 <= year <= 2005 and year != 1960:
+        if 1949 <= year <= 2005 and year != 1960:
             self._add_holiday("Tree Planting Day", APR, 5)
 
         # Birthday of the Buddha
@@ -107,14 +137,9 @@ class SouthKorea(
 
         # Children's Day
         if year >= 1975:
-            name = "Children's Day"
-            childrens_date = self._add_holiday(name, MAY, 5)
-            if self.observed and year >= 2015:
-                is_alt, alt_date = self.get_next_non_holiday(
-                    name, childrens_date, include_sat=True
-                )
-                if is_alt:
-                    self._add_holiday(alt_holiday + name, alt_date)
+            self._add_with_alt_holiday(
+                "Children's Day", date(year, MAY, 5), since=2015
+            )
 
         # Labour Day
         name = "Labour Day"
@@ -128,103 +153,40 @@ class SouthKorea(
 
         # Constitution Day
         # removed from holiday since 2008
-        if self.observed and 1948 <= year <= 2007:
+        if 1948 <= year <= 2007:
             self._add_holiday("Constitution Day", JUL, 17)
 
         # Liberation Day
         if year >= 1945:
-            name = "Liberation Day"
-            liberation_date = self._add_holiday(name, AUG, 15)
-            if self.observed and year >= 2021:
-                is_alt, alt_date = self.get_next_non_holiday(
-                    name, liberation_date, include_sat=True
-                )
-                if is_alt:
-                    self._add_holiday(alt_holiday + name, alt_date)
+            self._add_with_alt_holiday("Liberation Day", date(year, AUG, 15))
 
         # Korean Mid Autumn Day
         name = "Chuseok"
-        preceding_day_chuseok = "The day preceding of " + name
-        second_day_chuseok = "The second day of " + name
         chuseok_date = self._add_korean_calendar_holiday(name, 8, 15)
-        self._add_holiday(preceding_day_chuseok, chuseok_date + rd(days=-1))
-        self._add_holiday(second_day_chuseok, chuseok_date + rd(days=+1))
-
-        if self.observed and year >= 2014:
-            for cur_rd, cur_name in (
-                (-1, preceding_day_chuseok),
-                (0, name),
-                (+1, second_day_chuseok),
-            ):
-                target_date = chuseok_date + td(days=cur_rd)
-                is_alt, alt_date = self.get_next_non_holiday(
-                    cur_name, target_date
-                )
-                if is_alt:
-                    self._add_holiday(alt_holiday + name, alt_date)
+        self._add_holiday(preceding_day % name, chuseok_date + td(days=-1))
+        self._add_holiday(second_day % name, chuseok_date + td(days=+1))
+
+        for delta in (-1, 0, +1):
+            self._add_with_alt_holiday(
+                name,
+                chuseok_date + td(days=delta),
+                add_hol=False,
+                since=2014,
+                include_sat=False,
+            )
 
         # National Foundation Day
-        name = "National Foundation Day"
-        foundation_date = self._add_holiday(name, OCT, 3)
-        if self.observed and year >= 2021:
-            is_alt, alt_date = self.get_next_non_holiday(
-                name, foundation_date, include_sat=True
-            )
-            if is_alt:
-                self._add_holiday(alt_holiday + name, alt_date)
+        self._add_with_alt_holiday(
+            "National Foundation Day", date(year, OCT, 3)
+        )
 
-        # Hangul Day
+        # Hangeul Day
         if year <= 1990 or year >= 2013:
-            name = "Hangeul Day"
-            hangeul_date = self._add_holiday(name, OCT, 9)
-
-            if self.observed and year >= 2021:
-                is_alt, alt_date = self.get_next_non_holiday(
-                    name, hangeul_date, include_sat=True
-                )
-                if is_alt:
-                    self._add_holiday(alt_holiday + name, alt_date)
+            self._add_with_alt_holiday("Hangeul Day", date(year, OCT, 9))
 
         # Christmas Day
         self._add_christmas_day("Christmas Day")
 
-    def get_next_non_holiday(
-        self, name: str, cur: date, include_sat: bool = False
-    ) -> Tuple[bool, date]:
-        """Returns the first day from the date provided that's not already a
-        holiday of a different name nor a weekend.
-
-        :param name:
-           The name of the holiday.
-
-        :param cur:
-           The current date of the holiday.
-
-        :param include_sat:
-           Whether Saturday is to be considered a weekend in addition to
-           Sunday.
-
-        :return:
-           A tuple consisting of a flag set to whether the date is different
-           and the date itself.
-
-        """
-
-        start_value = cur
-        target_weekday = {SUN}
-        if include_sat:
-            target_weekday.add(SAT)
-        check_1 = cur.weekday() in target_weekday  # Exclude weekends
-        check_2 = (
-            cur in self and name != self[cur]
-        )  # Exclude if already a holiday
-        while check_1 or check_2:
-            cur += td(days=+1)
-            check_1 = cur.weekday() in target_weekday
-            check_2 = cur in self and name != self[cur]
-
-        return start_value != cur, cur
-
 
 class Korea(SouthKorea):
     def __init__(self, *args, **kwargs) -> None:
diff --git a/holidays/countries/ukraine.py b/holidays/countries/ukraine.py
index 2bd4d2e5..228041df 100644
--- a/holidays/countries/ukraine.py
+++ b/holidays/countries/ukraine.py
@@ -13,13 +13,13 @@ from datetime import date
 from datetime import timedelta as td
 from gettext import gettext as tr
 
-from dateutil.easter import EASTER_ORTHODOX, easter
-
-from holidays.constants import JAN, APR, MAR, MAY, JUN, JUL, AUG, OCT, NOV, DEC
+from holidays.calendars import GREGORIAN_CALENDAR, JULIAN_CALENDAR
+from holidays.constants import JAN, APR, JUN, JUL, AUG, OCT, NOV
 from holidays.holiday_base import HolidayBase
+from holidays.holiday_groups import ChristianHolidays, InternationalHolidays
 
 
-class Ukraine(HolidayBase):
+class Ukraine(HolidayBase, ChristianHolidays, InternationalHolidays):
     """
     Current holidays list:
     https://zakon1.rada.gov.ua/laws/show/322-08/paran454#n454
@@ -28,31 +28,12 @@ class Ukraine(HolidayBase):
     country = "UA"
     default_language = "uk"
 
-    def _populate(self, year):
-        def _add_with_observed(
-            hol_date: date, hol_name: str, days: int = 1
-        ) -> None:
-            self._add_holiday(hol_name, hol_date)
-            # 27.01.1995: holiday on weekend move to next workday
-            # https://zakon.rada.gov.ua/laws/show/35/95-вр
-            # 10.01.1998: cancelled
-            # https://zakon.rada.gov.ua/laws/show/785/97-вр
-            # 23.04.1999: holiday on weekend move to next workday
-            # https://zakon.rada.gov.ua/laws/show/576-14
-            if (
-                self.observed
-                and self._is_weekend(hol_date)
-                and (
-                    date(1995, JAN, 27) <= hol_date <= date(1998, JAN, 9)
-                    or hol_date >= date(1999, APR, 23)
-                )
-            ):
-                obs_date = hol_date + td(
-                    days=2 if self._is_saturday(hol_date) else days
-                )
-                hol_name = self.tr("%s (вихідний)") % self.tr(hol_name)
-                self._add_holiday(hol_name, obs_date)
+    def __init__(self, *args, **kwargs):
+        ChristianHolidays.__init__(self, JULIAN_CALENDAR)
+        InternationalHolidays.__init__(self)
+        super().__init__(*args, **kwargs)
 
+    def _populate(self, year):
         # The current set of holidays came into force in 1991
         if year <= 1990:
             return None
@@ -64,104 +45,117 @@ class Ukraine(HolidayBase):
             return None
 
         super()._populate(year)
+        observed_dates = set()
 
         # New Year's Day.
-        _add_with_observed(date(year, JAN, 1), tr("Новий рік"))
+        observed_dates.add(self._add_new_years_day(tr("Новий рік")))
 
-        _add_with_observed(
-            date(year, JAN, 7),
-            # Christmas (Julian calendar).
-            tr("Різдво Христове (за юліанським календарем)"),
+        observed_dates.add(
+            self._add_christmas_day(
+                # Christmas (Julian calendar).
+                tr("Різдво Христове (за юліанським календарем)")
+            )
         )
 
-        _add_with_observed(
-            date(year, MAR, 8),
-            # International Women's Day.
-            tr("Міжнародний жіночий день"),
+        # International Women's Day.
+        observed_dates.add(
+            self._add_womens_day(tr("Міжнародний жіночий день"))
         )
 
         # There is no holidays from March 15, 2022
         # https://zakon.rada.gov.ua/laws/show/2136-20#n26
-        if year >= 2022:
-            return None
-
-        easter_date = easter(year, method=EASTER_ORTHODOX)
-        # Easter Sunday (Pascha).
-        name = tr("Великдень (Пасха)")
-        if year == 2000:
-            _add_with_observed(easter_date, name, days=3)
-        elif year in {
-            2005,
-            2016,
-            2021,
-        }:
-            _add_with_observed(easter_date, name, days=2)
-        else:
-            _add_with_observed(easter_date, name)
-
-        # Holy Trinity Day.
-        _add_with_observed(easter_date + td(days=+49), tr("Трійця"))
-
-        dt = date(year, MAY, 1)
-        if year >= 2018:
-            # Labour Day.
-            name = tr("День праці")
-            _add_with_observed(dt, name)
-        else:
-            # International Workers' Solidarity Day.
-            name = tr("День міжнародної солідарності трудящих")
-            _add_with_observed(dt, name, days=2)
-            _add_with_observed(dt + td(days=+1), name, days=2)
-
-        dt = date(year, MAY, 9)
-        name = (
-            # Day of Victory over Nazism in World War II (Victory Day).
-            tr(
-                "День перемоги над нацизмом у Другій світовій війні "
-                "(День перемоги)"
-            )
-            if year >= 2016
-            # Victory Day.
-            else tr("День перемоги")
-        )
-        _add_with_observed(dt, name)
-
-        if year >= 1997:
-            _add_with_observed(
-                date(year, JUN, 28),
-                # Day of the Constitution of Ukraine.
-                tr("День Конституції України"),
+        if year <= 2021:
+            # Easter Sunday (Pascha).
+            observed_dates.add(
+                self._add_easter_sunday(tr("Великдень (Пасха)"))
             )
 
-        # Independence Day.
-        name = tr("День незалежності України")
-        if year >= 1992:
-            _add_with_observed(date(year, AUG, 24), name)
-        else:
-            self._add_holiday(name, JUL, 16)
+            # Holy Trinity Day.
+            observed_dates.add(self._add_whit_sunday(tr("Трійця")))
 
-        if year >= 2015:
             name = (
-                # Day of the defender of Ukraine.
-                tr("День захисників і захисниць України")
-                if year >= 2021
-                # Defender of Ukraine Day.
-                else tr("День захисника України")
+                # Labour Day.
+                tr("День праці")
+                if year >= 2018
+                # International Workers' Solidarity Day.
+                else tr("День міжнародної солідарності трудящих")
             )
-            _add_with_observed(date(year, OCT, 14), name)
-
-        if year <= 1999:
-            # Anniversary of the Great October Socialist Revolution.
-            name = tr("Річниця Великої Жовтневої соціалістичної революції")
-            _add_with_observed(date(year, NOV, 7), name, days=2)
-            _add_with_observed(date(year, NOV, 8), name, days=2)
-
-        if year >= 2017:
-            _add_with_observed(
-                date(year, DEC, 25),
-                # Christmas (Gregorian calendar).
-                tr("Різдво Христове (за григоріанським календарем)"),
+            may_1 = self._add_labour_day(name)
+            observed_dates.add(may_1)
+            if year <= 2017:
+                observed_dates.add(
+                    self._add_holiday(name, may_1 + td(days=+1))
+                )
+
+            name = (
+                # Day of Victory over Nazism in World War II (Victory Day).
+                tr(
+                    "День перемоги над нацизмом у Другій світовій війні "
+                    "(День перемоги)"
+                )
+                if year >= 2016
+                # Victory Day.
+                else tr("День перемоги")
             )
+            observed_dates.add(self._add_world_war_two_victory_day(name))
+
+            if year >= 1997:
+                observed_dates.add(
+                    # Day of the Constitution of Ukraine.
+                    self._add_holiday(tr("День Конституції України"), JUN, 28)
+                )
+
+            # Independence Day.
+            name = tr("День незалежності України")
+            if year >= 1992:
+                observed_dates.add(self._add_holiday(name, AUG, 24))
+            else:
+                self._add_holiday(name, JUL, 16)
+
+            if year >= 2015:
+                name = (
+                    # Day of defenders of Ukraine.
+                    tr("День захисників і захисниць України")
+                    if year >= 2021
+                    # Defender of Ukraine Day.
+                    else tr("День захисника України")
+                )
+                observed_dates.add(self._add_holiday(name, OCT, 14))
+
+            if year <= 1999:
+                # Anniversary of the Great October Socialist Revolution.
+                name = tr("Річниця Великої Жовтневої соціалістичної революції")
+                observed_dates.add(self._add_holiday(name, NOV, 7))
+                observed_dates.add(self._add_holiday(name, NOV, 8))
+
+            if year >= 2017:
+                observed_dates.add(
+                    self._add_christmas_day(
+                        # Christmas (Gregorian calendar).
+                        tr("Різдво Христове (за григоріанським календарем)"),
+                        GREGORIAN_CALENDAR,
+                    )
+                )
+
+        # 27.01.1995: holiday on weekend move to next workday
+        # https://zakon.rada.gov.ua/laws/show/35/95-вр
+        # 10.01.1998: cancelled
+        # https://zakon.rada.gov.ua/laws/show/785/97-вр
+        # 23.04.1999: holiday on weekend move to next workday
+        # https://zakon.rada.gov.ua/laws/show/576-14
+        if self.observed:
+            for dt in observed_dates:
+                if self._is_weekend(dt) and (
+                    date(1995, JAN, 27) <= dt <= date(1998, JAN, 9)
+                    or dt >= date(1999, APR, 23)
+                ):
+                    obs_date = dt + td(
+                        days=+2 if self._is_saturday(dt) else +1
+                    )
+                    while obs_date in self:
+                        obs_date += td(days=+1)
+                    hol_name = self.tr("%s (вихідний)") % self[dt]
+                    self._add_holiday(hol_name, obs_date)
 
 
 class UA(Ukraine):
diff --git a/holidays/countries/uruguay.py b/holidays/countries/uruguay.py
index d001069e..2dcb5745 100644
--- a/holidays/countries/uruguay.py
+++ b/holidays/countries/uruguay.py
@@ -10,17 +10,15 @@
 #  License: MIT (see LICENSE file)
 
 from datetime import date
-from datetime import timedelta as td
 from gettext import gettext as tr
 
-from dateutil.easter import easter
-
 from holidays.calendars import _get_nth_weekday_from
-from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, OCT, NOV, DEC, MON
+from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, OCT, MON
 from holidays.holiday_base import HolidayBase
+from holidays.holiday_groups import ChristianHolidays, InternationalHolidays
 
 
-class Uruguay(HolidayBase):
+class Uruguay(HolidayBase, ChristianHolidays, InternationalHolidays):
     """
     https://en.wikipedia.org/wiki/Public_holidays_in_Uruguay
     """
@@ -28,16 +26,21 @@ class Uruguay(HolidayBase):
     country = "UY"
     default_language = "es"
 
+    def __init__(self, *args, **kwargs) -> None:
+        ChristianHolidays.__init__(self)
+        InternationalHolidays.__init__(self)
+        super().__init__(*args, **kwargs)
+
     def _populate(self, year):
         super()._populate(year)
 
         # Mandatory paid holidays:
 
         # New Year's Day.
-        self._add_holiday(tr("Año Nuevo"), JAN, 1)
+        self._add_new_years_day(tr("Año Nuevo"))
 
         # International Workers' Day.
-        self._add_holiday(tr("Día de los Trabajadores"), MAY, 1)
+        self._add_labour_day(tr("Día de los Trabajadores"))
 
         # Constitution Day.
         self._add_holiday(tr("Jura de la Constitución"), JUL, 18)
@@ -46,7 +49,7 @@ class Uruguay(HolidayBase):
         self._add_holiday(tr("Día de la Independencia"), AUG, 25)
 
         # Day of the Family.
-        self._add_holiday(tr("Día de la Familia"), DEC, 25)
+        self._add_christmas_day(tr("Día de la Familia"))
 
         # Partially paid holidays:
 
@@ -57,23 +60,21 @@ class Uruguay(HolidayBase):
         self._add_holiday(tr("Natalicio de José Gervasio Artigas"), JUN, 19)
 
         # All Souls' Day.
-        self._add_holiday(tr("Día de los Difuntos"), NOV, 2)
+        self._add_all_souls_day(tr("Día de los Difuntos"))
 
         # Moveable holidays:
 
-        easter_date = easter(year)
-
         # Carnival Day.
         name = tr("Día de Carnaval")
-        self._add_holiday(name, easter_date + td(days=-48))
-        self._add_holiday(name, easter_date + td(days=-47))
+        self._add_carnival_monday(name)
+        self._add_carnival_tuesday(name)
 
         # Maundy Thursday.
-        self._add_holiday(tr("Jueves Santo"), easter_date + td(days=-3))
+        self._add_holy_thursday(tr("Jueves Santo"))
         # Good Friday.
-        self._add_holiday(tr("Viernes Santo"), easter_date + td(days=-2))
+        self._add_good_friday(tr("Viernes Santo"))
         # Easter Day.
-        self._add_holiday(tr("Día de Pascuas"), easter_date)
+        self._add_easter_sunday(tr("Día de Pascuas"))
 
         holiday_pairs = (
             (
diff --git a/holidays/countries/venezuela.py b/holidays/countries/venezuela.py
index 88790f64..8658fd28 100644
--- a/holidays/countries/venezuela.py
+++ b/holidays/countries/venezuela.py
@@ -9,16 +9,14 @@
 #  Website: https://github.com/dr-prodigy/python-holidays
 #  License: MIT (see LICENSE file)
 
-from datetime import timedelta as td
 from gettext import gettext as tr
 
-from dateutil.easter import easter
-
-from holidays.constants import JAN, APR, MAY, JUN, JUL, OCT, DEC
+from holidays.constants import APR, JUN, JUL, OCT
 from holidays.holiday_base import HolidayBase
+from holidays.holiday_groups import ChristianHolidays, InternationalHolidays
 
 
-class Venezuela(HolidayBase):
+class Venezuela(HolidayBase, ChristianHolidays, InternationalHolidays):
     """
     https://dias-festivos.eu/dias-festivos/venezuela/#
     """
@@ -26,6 +24,11 @@ class Venezuela(HolidayBase):
     country = "VE"
     default_language = "es"
 
+    def __init__(self, *args, **kwargs) -> None:
+        ChristianHolidays.__init__(self)
+        InternationalHolidays.__init__(self)
+        super().__init__(*args, **kwargs)
+
     def _populate(self, year):
         super()._populate(year)
 
@@ -41,21 +44,19 @@ class Venezuela(HolidayBase):
         """
 
         # New Year's Day.
-        self._add_holiday(tr("Año Nuevo"), JAN, 1)
-
-        easter_date = easter(year)
+        self._add_new_years_day(tr("Año Nuevo"))
 
         # Monday of Carnival.
-        self._add_holiday(tr("Lunes de Carnaval"), easter_date + td(days=-48))
+        self._add_carnival_monday(tr("Lunes de Carnaval"))
 
         # Tuesday of Carnival.
-        self._add_holiday(tr("Martes de Carnaval"), easter_date + td(days=-47))
+        self._add_carnival_tuesday(tr("Martes de Carnaval"))
 
         # Maundy Thursday.
-        self._add_holiday(tr("Jueves Santo"), easter_date + td(days=-3))
+        self._add_holy_thursday(tr("Jueves Santo"))
 
         # Good Friday.
-        self._add_holiday(tr("Viernes Santo"), easter_date + td(days=-2))
+        self._add_good_friday(tr("Viernes Santo"))
 
         # Note: not sure about the start year, but this event happened in 1811
         if year >= 1811:
@@ -65,7 +66,7 @@ class Venezuela(HolidayBase):
         # https://bit.ly/3B4Xd1L
         if year >= 1946:
             # International Worker's Day.
-            self._add_holiday(tr("Dia Mundial del Trabajador"), MAY, 1)
+            self._add_labour_day(tr("Dia Mundial del Trabajador"))
 
         # Note: not sure about the start year, but this event happened in 1824
         if year >= 1971 or 1824 <= year <= 1917:
@@ -95,13 +96,13 @@ class Venezuela(HolidayBase):
             self._add_holiday(tr("Día Festivo Desconocido"), OCT, 28)
 
         # Christmas Eve.
-        self._add_holiday(tr("Nochebuena"), DEC, 24)
+        self._add_christmas_eve(tr("Nochebuena"))
 
         # Christmas Day.
-        self._add_holiday(tr("Día de Navidad"), DEC, 25)
+        self._add_christmas_day(tr("Día de Navidad"))
 
         # New Year's Eve.
-        self._add_holiday(tr("Fiesta de Fin de Año"), DEC, 31)
+        self._add_new_years_eve(tr("Fiesta de Fin de Año"))
 
 
 class VE(Venezuela):
diff --git a/holidays/locale/en_US/LC_MESSAGES/FR.po b/holidays/locale/en_US/LC_MESSAGES/FR.po
new file mode 100644
index 00000000..64f1021c
--- /dev/null
+++ b/holidays/locale/en_US/LC_MESSAGES/FR.po
@@ -0,0 +1,127 @@
+# France holidays en_US localization.
+# Authors: ~Jhellico <jhellico@gmail.com>, (c) 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Python Holidays 0.22\n"
+"POT-Creation-Date: 2023-03-23 14:44+0200\n"
+"PO-Revision-Date: 2023-03-23 14:47+0200\n"
+"Last-Translator: ~Jhellico <jhellico@gmail.com>\n"
+"Language-Team: Python Holidays localization team\n"
+"Language: en_US\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: Lingua 4.15.0\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#. New Year's Day.
+#: holidays/countries/france.py:64
+msgid "Jour de l'an"
+msgstr "New Year's Day"
+
+#. Labor Day.
+#: holidays/countries/france.py:69
+msgid "Fête du Travail"
+msgstr "Labor Day"
+
+#. Labor and Social Concord Day.
+#: holidays/countries/france.py:72
+msgid "Fête du Travail et de la Concorde sociale"
+msgstr "Labor and Social Concord Day"
+
+#. Victory Day.
+#: holidays/countries/france.py:77
+msgid "Fête de la Victoire"
+msgstr "Victory Day"
+
+#. National Day.
+#: holidays/countries/france.py:81
+msgid "Fête nationale"
+msgstr "National Day"
+
+#. Armistice Day.
+#: holidays/countries/france.py:85
+msgid "Armistice"
+msgstr "Armistice Day"
+
+#. Good Friday.
+#: holidays/countries/france.py:96
+msgid "Vendredi saint"
+msgstr "Good Friday"
+
+#. Mi-Careme.
+#: holidays/countries/france.py:101
+msgid "Mi-Carême"
+msgstr "Mi-Careme"
+
+#. Easter Monday.
+#: holidays/countries/france.py:106
+msgid "Lundi de Pâques"
+msgstr "Easter Monday"
+
+#. Whit Monday.
+#: holidays/countries/france.py:110
+msgid "Lundi de Pentecôte"
+msgstr "Whit Monday"
+
+#. Ascension Day.
+#: holidays/countries/france.py:114
+msgid "Ascension"
+msgstr "Ascension Day"
+
+#. Assumption Day.
+#: holidays/countries/france.py:116
+msgid "Assomption"
+msgstr "Assumption Day"
+
+#. All Saints' Day.
+#: holidays/countries/france.py:118
+msgid "Toussaint"
+msgstr "All Saints' Day"
+
+#. Christmas Day.
+#: holidays/countries/france.py:120
+msgid "Noël"
+msgstr "Christmas Day"
+
+#. Feast of Victor Schoelcher.
+#: holidays/countries/france.py:126
+msgid "Fête de Victor Schoelcher"
+msgstr "Feast of Victor Schoelcher"
+
+#. Abolition of slavery.
+#: holidays/countries/france.py:129
+msgid "Abolition de l'esclavage"
+msgstr "Abolition of Slavery"
+
+#. Saint Stephen's Day.
+#: holidays/countries/france.py:133
+msgid "Saint Étienne"
+msgstr "Saint Stephen's Day"
+
+#. Citizenship Day.
+#: holidays/countries/france.py:152
+msgid "Fête de la Citoyenneté"
+msgstr "Citizenship Day"
+
+#. Missionary Day.
+#: holidays/countries/france.py:156
+msgid "Arrivée de l'Évangile"
+msgstr "Missionary Day"
+
+#. Internal Autonomy Day.
+#: holidays/countries/france.py:158
+msgid "Fête de l'autonomie"
+msgstr "Internal Autonomy Day"
+
+#. Feast of Saint Peter Chanel.
+#: holidays/countries/france.py:168
+msgid "Saint Pierre Chanel"
+msgstr "Feast of Saint Peter Chanel"
+
+#. Festival of the territory
+#: holidays/countries/france.py:170
+msgid "Fête du Territoire"
+msgstr "Festival of the Territory"
diff --git a/holidays/locale/en_US/LC_MESSAGES/UY.po b/holidays/locale/en_US/LC_MESSAGES/UY.po
index 546fde27..c6e51057 100644
--- a/holidays/locale/en_US/LC_MESSAGES/UY.po
+++ b/holidays/locale/en_US/LC_MESSAGES/UY.po
@@ -17,76 +17,76 @@ msgstr ""
 "X-Generator: Poedit 3.2.2\n"
 
 #. New Year's Day.
-#: holidays/countries/uruguay.py:36
+#: ./holidays/countries/uruguay.py:40
 msgid "Año Nuevo"
 msgstr "New Year's Day"
 
 #. International Workers' Day.
-#: holidays/countries/uruguay.py:39
+#: ./holidays/countries/uruguay.py:43
 msgid "Día de los Trabajadores"
 msgstr "International Workers' Day"
 
 #. Constitution Day.
-#: holidays/countries/uruguay.py:42
+#: ./holidays/countries/uruguay.py:46
 msgid "Jura de la Constitución"
 msgstr "Constitution Day"
 
 #. Independence Day.
-#: holidays/countries/uruguay.py:45
+#: ./holidays/countries/uruguay.py:49
 msgid "Día de la Independencia"
 msgstr "Independence Day"
 
 #. Day of the Family.
-#: holidays/countries/uruguay.py:48
+#: ./holidays/countries/uruguay.py:52
 msgid "Día de la Familia"
 msgstr "Day of the Family"
 
 #. Children's Day.
-#: holidays/countries/uruguay.py:53
+#: ./holidays/countries/uruguay.py:57
 msgid "Día de los Niños"
 msgstr "Children's Day"
 
 #. Birthday of José Gervasio Artigas.
-#: holidays/countries/uruguay.py:56
+#: ./holidays/countries/uruguay.py:60
 msgid "Natalicio de José Gervasio Artigas"
 msgstr "Birthday of José Gervasio Artigas"
 
 #. All Souls' Day.
-#: holidays/countries/uruguay.py:61
+#: ./holidays/countries/uruguay.py:63
 msgid "Día de los Difuntos"
 msgstr "All Souls' Day"
 
 #. Carnival Day.
-#: holidays/countries/uruguay.py:68
+#: ./holidays/countries/uruguay.py:68
 msgid "Día de Carnaval"
 msgstr "Carnival Day"
 
 #. Maundy Thursday.
-#: holidays/countries/uruguay.py:73
+#: ./holidays/countries/uruguay.py:73
 msgid "Jueves Santo"
 msgstr "Maundy Thursday"
 
 #. Good Friday.
-#: holidays/countries/uruguay.py:75
+#: ./holidays/countries/uruguay.py:75
 msgid "Viernes Santo"
 msgstr "Good Friday"
 
 #. Easter Day.
-#: holidays/countries/uruguay.py:77
+#: ./holidays/countries/uruguay.py:77
 msgid "Día de Pascuas"
 msgstr "Easter Day"
 
 #. Landing of the 33 Patriots.
-#: holidays/countries/uruguay.py:83
+#: ./holidays/countries/uruguay.py:83
 msgid "Desembarco de los 33 Orientales"
 msgstr "Landing of the 33 Patriots"
 
 #. Battle of Las Piedras.
-#: holidays/countries/uruguay.py:88
+#: ./holidays/countries/uruguay.py:88
 msgid "Batalla de Las Piedras"
 msgstr "Battle of Las Piedras"
 
 #. Respect for Cultural Diversity Day.
-#: holidays/countries/uruguay.py:93
+#: ./holidays/countries/uruguay.py:93
 msgid "Día del Respeto a la Diversidad Cultural"
 msgstr "Respect for Cultural Diversity Day"
diff --git a/holidays/locale/en_US/LC_MESSAGES/VE.po b/holidays/locale/en_US/LC_MESSAGES/VE.po
index ffd65113..a8e1c468 100644
--- a/holidays/locale/en_US/LC_MESSAGES/VE.po
+++ b/holidays/locale/en_US/LC_MESSAGES/VE.po
@@ -17,81 +17,81 @@ msgstr ""
 "X-Generator: Poedit 3.2.2\n"
 
 #. New Year's Day.
-#: holidays/countries/venezuela.py:44
+#: ./holidays/countries/venezuela.py:47
 msgid "Año Nuevo"
 msgstr "New Year's Day"
 
 #. Monday of Carnival.
-#: holidays/countries/venezuela.py:49
+#: ./holidays/countries/venezuela.py:50
 msgid "Lunes de Carnaval"
 msgstr "Monday of Carnival"
 
 #. Tuesday of Carnival.
-#: holidays/countries/venezuela.py:52
+#: ./holidays/countries/venezuela.py:53
 msgid "Martes de Carnaval"
 msgstr "Tuesday of Carnival"
 
 #. Maundy Thursday.
-#: holidays/countries/venezuela.py:55
+#: ./holidays/countries/venezuela.py:56
 msgid "Jueves Santo"
 msgstr "Maundy Thursday"
 
 #. Good Friday.
-#: holidays/countries/venezuela.py:58
+#: ./holidays/countries/venezuela.py:59
 msgid "Viernes Santo"
 msgstr "Good Friday"
 
 #. Declaration of Independence.
-#: holidays/countries/venezuela.py:63
+#: ./holidays/countries/venezuela.py:64
 msgid "Declaración de la Independencia"
 msgstr "Declaration of Independence"
 
 #. International Worker's Day.
-#: holidays/countries/venezuela.py:70
+#: ./holidays/countries/venezuela.py:69
 msgid "Dia Mundial del Trabajador"
 msgstr "International Worker's Day"
 
 #. Battle of Carabobo.
-#: holidays/countries/venezuela.py:75
+#: ./holidays/countries/venezuela.py:74
 msgid "Batalla de Carabobo"
 msgstr "Battle of Carabobo"
 
 #. Independence Day.
-#: holidays/countries/venezuela.py:80
+#: ./holidays/countries/venezuela.py:79
 msgid "Día de la Independencia"
 msgstr "Independence Day"
 
 #. Birthday of Simon Bolivar.
-#: holidays/countries/venezuela.py:84
+#: ./holidays/countries/venezuela.py:83
 msgid "Natalicio de Simón Bolívar"
 msgstr "Birthday of Simon Bolivar"
 
 #. Day of Indigenous Resistance.
-#: holidays/countries/venezuela.py:88
+#: ./holidays/countries/venezuela.py:87
 msgid "Día de la Resistencia Indígena"
 msgstr "Day of Indigenous Resistance"
 
 #. Columbus Day.
-#: holidays/countries/venezuela.py:93
+#: ./holidays/countries/venezuela.py:90
 msgid "Día de la Raza"
 msgstr "Columbus Day"
 
 #. Unknown Holiday.
-#: holidays/countries/venezuela.py:99
+#: ./holidays/countries/venezuela.py:96
 msgid "Día Festivo Desconocido"
 msgstr "Unknown Holiday"
 
 #. Christmas Eve.
-#: holidays/countries/venezuela.py:102
+#: ./holidays/countries/venezuela.py:99
 msgid "Nochebuena"
 msgstr "Christmas Eve"
 
 #. Christmas Day.
-#: holidays/countries/venezuela.py:105
+#: ./holidays/countries/venezuela.py:102
 msgid "Día de Navidad"
 msgstr "Christmas Day"
 
 #. New Year's Eve.
-#: holidays/countries/venezuela.py:108
+#: ./holidays/countries/venezuela.py:105
 msgid "Fiesta de Fin de Año"
 msgstr "New Year's Eve"
diff --git a/holidays/locale/es/LC_MESSAGES/UY.po b/holidays/locale/es/LC_MESSAGES/UY.po
index 15d17bb0..88500b27 100644
--- a/holidays/locale/es/LC_MESSAGES/UY.po
+++ b/holidays/locale/es/LC_MESSAGES/UY.po
@@ -17,76 +17,76 @@ msgstr ""
 "X-Generator: Poedit 3.2.2\n"
 
 #. New Year's Day.
-#: holidays/countries/uruguay.py:36
+#: ./holidays/countries/uruguay.py:40
 msgid "Año Nuevo"
 msgstr ""
 
 #. International Workers' Day.
-#: holidays/countries/uruguay.py:39
+#: ./holidays/countries/uruguay.py:43
 msgid "Día de los Trabajadores"
 msgstr ""
 
 #. Constitution Day.
-#: holidays/countries/uruguay.py:42
+#: ./holidays/countries/uruguay.py:46
 msgid "Jura de la Constitución"
 msgstr ""
 
 #. Independence Day.
-#: holidays/countries/uruguay.py:45
+#: ./holidays/countries/uruguay.py:49
 msgid "Día de la Independencia"
 msgstr ""
 
 #. Day of the Family.
-#: holidays/countries/uruguay.py:48
+#: ./holidays/countries/uruguay.py:52
 msgid "Día de la Familia"
 msgstr ""
 
 #. Children's Day.
-#: holidays/countries/uruguay.py:53
+#: ./holidays/countries/uruguay.py:57
 msgid "Día de los Niños"
 msgstr ""
 
 #. Birthday of José Gervasio Artigas.
-#: holidays/countries/uruguay.py:56
+#: ./holidays/countries/uruguay.py:60
 msgid "Natalicio de José Gervasio Artigas"
 msgstr ""
 
 #. All Souls' Day.
-#: holidays/countries/uruguay.py:61
+#: ./holidays/countries/uruguay.py:63
 msgid "Día de los Difuntos"
 msgstr ""
 
 #. Carnival Day.
-#: holidays/countries/uruguay.py:68
+#: ./holidays/countries/uruguay.py:68
 msgid "Día de Carnaval"
 msgstr ""
 
 #. Maundy Thursday.
-#: holidays/countries/uruguay.py:73
+#: ./holidays/countries/uruguay.py:73
 msgid "Jueves Santo"
 msgstr ""
 
 #. Good Friday.
-#: holidays/countries/uruguay.py:75
+#: ./holidays/countries/uruguay.py:75
 msgid "Viernes Santo"
 msgstr ""
 
 #. Easter Day.
-#: holidays/countries/uruguay.py:77
+#: ./holidays/countries/uruguay.py:77
 msgid "Día de Pascuas"
 msgstr ""
 
 #. Landing of the 33 Patriots.
-#: holidays/countries/uruguay.py:83
+#: ./holidays/countries/uruguay.py:83
 msgid "Desembarco de los 33 Orientales"
 msgstr ""
 
 #. Battle of Las Piedras.
-#: holidays/countries/uruguay.py:88
+#: ./holidays/countries/uruguay.py:88
 msgid "Batalla de Las Piedras"
 msgstr ""
 
 #. Respect for Cultural Diversity Day.
-#: holidays/countries/uruguay.py:93
+#: ./holidays/countries/uruguay.py:93
 msgid "Día del Respeto a la Diversidad Cultural"
 msgstr ""
diff --git a/holidays/locale/es/LC_MESSAGES/VE.po b/holidays/locale/es/LC_MESSAGES/VE.po
index 8e2baf92..65fa99eb 100644
--- a/holidays/locale/es/LC_MESSAGES/VE.po
+++ b/holidays/locale/es/LC_MESSAGES/VE.po
@@ -17,81 +17,81 @@ msgstr ""
 "X-Generator: Poedit 3.2.2\n"
 
 #. New Year's Day.
-#: holidays/countries/venezuela.py:44
+#: ./holidays/countries/venezuela.py:47
 msgid "Año Nuevo"
 msgstr ""
 
 #. Monday of Carnival.
-#: holidays/countries/venezuela.py:49
+#: ./holidays/countries/venezuela.py:50
 msgid "Lunes de Carnaval"
 msgstr ""
 
 #. Tuesday of Carnival.
-#: holidays/countries/venezuela.py:52
+#: ./holidays/countries/venezuela.py:53
 msgid "Martes de Carnaval"
 msgstr ""
 
 #. Maundy Thursday.
-#: holidays/countries/venezuela.py:55
+#: ./holidays/countries/venezuela.py:56
 msgid "Jueves Santo"
 msgstr ""
 
 #. Good Friday.
-#: holidays/countries/venezuela.py:58
+#: ./holidays/countries/venezuela.py:59
 msgid "Viernes Santo"
 msgstr ""
 
 #. Declaration of Independence.
-#: holidays/countries/venezuela.py:63
+#: ./holidays/countries/venezuela.py:64
 msgid "Declaración de la Independencia"
 msgstr ""
 
 #. International Worker's Day.
-#: holidays/countries/venezuela.py:70
+#: ./holidays/countries/venezuela.py:69
 msgid "Dia Mundial del Trabajador"
 msgstr ""
 
 #. Battle of Carabobo.
-#: holidays/countries/venezuela.py:75
+#: ./holidays/countries/venezuela.py:74
 msgid "Batalla de Carabobo"
 msgstr ""
 
 #. Independence Day.
-#: holidays/countries/venezuela.py:80
+#: ./holidays/countries/venezuela.py:79
 msgid "Día de la Independencia"
 msgstr ""
 
-#. Birth of Simon Bolivar.
-#: holidays/countries/venezuela.py:84
+#. Birthday of Simon Bolivar.
+#: ./holidays/countries/venezuela.py:83
 msgid "Natalicio de Simón Bolívar"
 msgstr ""
 
 #. Day of Indigenous Resistance.
-#: holidays/countries/venezuela.py:88
+#: ./holidays/countries/venezuela.py:87
 msgid "Día de la Resistencia Indígena"
 msgstr ""
 
 #. Columbus Day.
-#: holidays/countries/venezuela.py:93
+#: ./holidays/countries/venezuela.py:90
 msgid "Día de la Raza"
 msgstr ""
 
 #. Unknown Holiday.
-#: holidays/countries/venezuela.py:99
+#: ./holidays/countries/venezuela.py:96
 msgid "Día Festivo Desconocido"
 msgstr ""
 
 #. Christmas Eve.
-#: holidays/countries/venezuela.py:102
+#: ./holidays/countries/venezuela.py:99
 msgid "Nochebuena"
 msgstr ""
 
 #. Christmas Day.
-#: holidays/countries/venezuela.py:105
+#: ./holidays/countries/venezuela.py:102
 msgid "Día de Navidad"
 msgstr ""
 
 #. New Year's Eve.
-#: holidays/countries/venezuela.py:108
+#: ./holidays/countries/venezuela.py:105
 msgid "Fiesta de Fin de Año"
 msgstr ""
diff --git a/holidays/locale/fr/LC_MESSAGES/FR.po b/holidays/locale/fr/LC_MESSAGES/FR.po
new file mode 100644
index 00000000..bbffc135
--- /dev/null
+++ b/holidays/locale/fr/LC_MESSAGES/FR.po
@@ -0,0 +1,127 @@
+# France holidays.
+# Authors: ~Jhellico <jhellico@gmail.com>, (c) 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Python Holidays 0.22\n"
+"POT-Creation-Date: 2023-03-23 14:44+0200\n"
+"PO-Revision-Date: 2023-03-23 14:45+0200\n"
+"Last-Translator: ~Jhellico <jhellico@gmail.com>\n"
+"Language-Team: Python Holidays localization team\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"Generated-By: Lingua 4.15.0\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#. New Year's Day.
+#: holidays/countries/france.py:64
+msgid "Jour de l'an"
+msgstr ""
+
+#. Labor Day.
+#: holidays/countries/france.py:69
+msgid "Fête du Travail"
+msgstr ""
+
+#. Labor and Social Concord Day.
+#: holidays/countries/france.py:72
+msgid "Fête du Travail et de la Concorde sociale"
+msgstr ""
+
+#. Victory Day.
+#: holidays/countries/france.py:77
+msgid "Fête de la Victoire"
+msgstr ""
+
+#. National Day.
+#: holidays/countries/france.py:81
+msgid "Fête nationale"
+msgstr ""
+
+#. Armistice Day.
+#: holidays/countries/france.py:85
+msgid "Armistice"
+msgstr ""
+
+#. Good Friday.
+#: holidays/countries/france.py:96
+msgid "Vendredi saint"
+msgstr ""
+
+#. Mi-Careme.
+#: holidays/countries/france.py:101
+msgid "Mi-Carême"
+msgstr ""
+
+#. Easter Monday.
+#: holidays/countries/france.py:106
+msgid "Lundi de Pâques"
+msgstr ""
+
+#. Whit Monday.
+#: holidays/countries/france.py:110
+msgid "Lundi de Pentecôte"
+msgstr ""
+
+#. Ascension Day.
+#: holidays/countries/france.py:114
+msgid "Ascension"
+msgstr ""
+
+#. Assumption Day.
+#: holidays/countries/france.py:116
+msgid "Assomption"
+msgstr ""
+
+#. All Saints' Day.
+#: holidays/countries/france.py:118
+msgid "Toussaint"
+msgstr ""
+
+#. Christmas Day.
+#: holidays/countries/france.py:120
+msgid "Noël"
+msgstr ""
+
+#. Feast of Victor Schoelcher.
+#: holidays/countries/france.py:126
+msgid "Fête de Victor Schoelcher"
+msgstr ""
+
+#. Abolition of slavery.
+#: holidays/countries/france.py:129
+msgid "Abolition de l'esclavage"
+msgstr ""
+
+#. Saint Stephen's Day.
+#: holidays/countries/france.py:133
+msgid "Saint Étienne"
+msgstr ""
+
+#. Citizenship Day.
+#: holidays/countries/france.py:152
+msgid "Fête de la Citoyenneté"
+msgstr ""
+
+#. Missionary Day.
+#: holidays/countries/france.py:156
+msgid "Arrivée de l'Évangile"
+msgstr ""
+
+#. Internal Autonomy Day.
+#: holidays/countries/france.py:158
+msgid "Fête de l'autonomie"
+msgstr ""
+
+#. Feast of Saint Peter Chanel.
+#: holidays/countries/france.py:168
+msgid "Saint Pierre Chanel"
+msgstr ""
+
+#. Festival of the territory
+#: holidays/countries/france.py:170
+msgid "Fête du Territoire"
+msgstr ""
diff --git a/holidays/locale/uk/LC_MESSAGES/FR.po b/holidays/locale/uk/LC_MESSAGES/FR.po
new file mode 100644
index 00000000..c8c23fd1
--- /dev/null
+++ b/holidays/locale/uk/LC_MESSAGES/FR.po
@@ -0,0 +1,128 @@
+# France holidays uk localization.
+# Authors: ~Jhellico <jhellico@gmail.com>, (c) 2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Python Holidays 0.22\n"
+"POT-Creation-Date: 2023-03-23 14:44+0200\n"
+"PO-Revision-Date: 2023-03-23 14:47+0200\n"
+"Last-Translator: ~Jhellico <jhellico@gmail.com>\n"
+"Language-Team: Python Holidays localization team\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
+"Generated-By: Lingua 4.15.0\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#. New Year's Day.
+#: holidays/countries/france.py:64
+msgid "Jour de l'an"
+msgstr "Новий рік"
+
+#. Labor Day.
+#: holidays/countries/france.py:69
+msgid "Fête du Travail"
+msgstr "День Праці"
+
+#. Labor and Social Concord Day.
+#: holidays/countries/france.py:72
+msgid "Fête du Travail et de la Concorde sociale"
+msgstr "День Праці та Суспільної згоди"
+
+#. Victory Day.
+#: holidays/countries/france.py:77
+msgid "Fête de la Victoire"
+msgstr "День Перемоги"
+
+#. National Day.
+#: holidays/countries/france.py:81
+msgid "Fête nationale"
+msgstr "Національне свято"
+
+#. Armistice Day.
+#: holidays/countries/france.py:85
+msgid "Armistice"
+msgstr "День перемирʼя (закінчення Першої світової війни)"
+
+#. Good Friday.
+#: holidays/countries/france.py:96
+msgid "Vendredi saint"
+msgstr "Страсна пʼятниця"
+
+#. Mi-Careme.
+#: holidays/countries/france.py:101
+msgid "Mi-Carême"
+msgstr "Свято Мі-Карем"
+
+#. Easter Monday.
+#: holidays/countries/france.py:106
+msgid "Lundi de Pâques"
+msgstr "Великодній понеділок"
+
+#. Whit Monday.
+#: holidays/countries/france.py:110
+msgid "Lundi de Pentecôte"
+msgstr "День Святого Духа"
+
+#. Ascension Day.
+#: holidays/countries/france.py:114
+msgid "Ascension"
+msgstr "Вознесіння Господнє"
+
+#. Assumption Day.
+#: holidays/countries/france.py:116
+msgid "Assomption"
+msgstr "Внебовзяття Пресвятої Діви Марії"
+
+#. All Saints' Day.
+#: holidays/countries/france.py:118
+msgid "Toussaint"
+msgstr "День усіх святих"
+
+#. Christmas Day.
+#: holidays/countries/france.py:120
+msgid "Noël"
+msgstr "Різдво Христове"
+
+#. Feast of Victor Schoelcher.
+#: holidays/countries/france.py:126
+msgid "Fête de Victor Schoelcher"
+msgstr "День Віктора Шольшера"
+
+#. Abolition of slavery.
+#: holidays/countries/france.py:129
+msgid "Abolition de l'esclavage"
+msgstr "День скасування рабства"
+
+#. Saint Stephen's Day.
+#: holidays/countries/france.py:133
+msgid "Saint Étienne"
+msgstr "День Святого Стефана"
+
+#. Citizenship Day.
+#: holidays/countries/france.py:152
+msgid "Fête de la Citoyenneté"
+msgstr "День громадянства"
+
+#. Missionary Day.
+#: holidays/countries/france.py:156
+msgid "Arrivée de l'Évangile"
+msgstr "День місіонерів"
+
+#. Internal Autonomy Day.
+#: holidays/countries/france.py:158
+msgid "Fête de l'autonomie"
+msgstr "День автономії"
+
+#. Feast of Saint Peter Chanel.
+#: holidays/countries/france.py:168
+msgid "Saint Pierre Chanel"
+msgstr "День Святого Пʼєра Шанеля"
+
+#. Festival of the territory
+#: holidays/countries/france.py:170
+msgid "Fête du Territoire"
+msgstr "День Території"
diff --git a/holidays/locale/uk/LC_MESSAGES/UY.po b/holidays/locale/uk/LC_MESSAGES/UY.po
index e6992a74..b8614a75 100644
--- a/holidays/locale/uk/LC_MESSAGES/UY.po
+++ b/holidays/locale/uk/LC_MESSAGES/UY.po
@@ -18,76 +18,76 @@ msgstr ""
 "X-Generator: Poedit 3.2.2\n"
 
 #. New Year's Day.
-#: holidays/countries/uruguay.py:36
+#: ./holidays/countries/uruguay.py:40
 msgid "Año Nuevo"
 msgstr "Новий рік"
 
 #. International Workers' Day.
-#: holidays/countries/uruguay.py:39
+#: ./holidays/countries/uruguay.py:43
 msgid "Día de los Trabajadores"
 msgstr "День трудящих"
 
 #. Constitution Day.
-#: holidays/countries/uruguay.py:42
+#: ./holidays/countries/uruguay.py:46
 msgid "Jura de la Constitución"
 msgstr "День присяги Конституції"
 
 #. Independence Day.
-#: holidays/countries/uruguay.py:45
+#: ./holidays/countries/uruguay.py:49
 msgid "Día de la Independencia"
 msgstr "День незалежності"
 
 #. Day of the Family.
-#: holidays/countries/uruguay.py:48
+#: ./holidays/countries/uruguay.py:52
 msgid "Día de la Familia"
 msgstr "День родини"
 
 #. Children's Day.
-#: holidays/countries/uruguay.py:53
+#: ./holidays/countries/uruguay.py:57
 msgid "Día de los Niños"
 msgstr "День захисту дітей"
 
 #. Birthday of José Gervasio Artigas.
-#: holidays/countries/uruguay.py:56
+#: ./holidays/countries/uruguay.py:60
 msgid "Natalicio de José Gervasio Artigas"
 msgstr "Річниця Хосе Гервасіо Артіґаса"
 
 #. All Souls' Day.
-#: holidays/countries/uruguay.py:61
+#: ./holidays/countries/uruguay.py:63
 msgid "Día de los Difuntos"
 msgstr "День усіх померлих"
 
 #. Carnival Day.
-#: holidays/countries/uruguay.py:68
+#: ./holidays/countries/uruguay.py:68
 msgid "Día de Carnaval"
 msgstr "Карнавал"
 
 #. Maundy Thursday.
-#: holidays/countries/uruguay.py:73
+#: ./holidays/countries/uruguay.py:73
 msgid "Jueves Santo"
 msgstr "Великий четвер"
 
 #. Good Friday.
-#: holidays/countries/uruguay.py:75
+#: ./holidays/countries/uruguay.py:75
 msgid "Viernes Santo"
 msgstr "Страсна пʼятниця"
 
 #. Easter Day.
-#: holidays/countries/uruguay.py:77
+#: ./holidays/countries/uruguay.py:77
 msgid "Día de Pascuas"
 msgstr "Великдень"
 
 #. Landing of the 33 Patriots.
-#: holidays/countries/uruguay.py:83
+#: ./holidays/countries/uruguay.py:83
 msgid "Desembarco de los 33 Orientales"
 msgstr "День висадки 33 патріотів"
 
 #. Battle of Las Piedras.
-#: holidays/countries/uruguay.py:88
+#: ./holidays/countries/uruguay.py:88
 msgid "Batalla de Las Piedras"
 msgstr "День битви при Лас-Пʼєдрас"
 
 #. Respect for Cultural Diversity Day.
-#: holidays/countries/uruguay.py:93
+#: ./holidays/countries/uruguay.py:93
 msgid "Día del Respeto a la Diversidad Cultural"
 msgstr "День поваги до культурного різноманіття"
diff --git a/holidays/locale/uk/LC_MESSAGES/VE.po b/holidays/locale/uk/LC_MESSAGES/VE.po
index a692ffcb..525e2415 100644
--- a/holidays/locale/uk/LC_MESSAGES/VE.po
+++ b/holidays/locale/uk/LC_MESSAGES/VE.po
@@ -18,81 +18,81 @@ msgstr ""
 "X-Generator: Poedit 3.2.2\n"
 
 #. New Year's Day.
-#: holidays/countries/venezuela.py:44
+#: ./holidays/countries/venezuela.py:47
 msgid "Año Nuevo"
 msgstr "Новий рік"
 
 #. Monday of Carnival.
-#: holidays/countries/venezuela.py:49
+#: ./holidays/countries/venezuela.py:50
 msgid "Lunes de Carnaval"
 msgstr "Карнавальний понеділок"
 
 #. Tuesday of Carnival.
-#: holidays/countries/venezuela.py:52
+#: ./holidays/countries/venezuela.py:53
 msgid "Martes de Carnaval"
 msgstr "Карнавальний вівторок"
 
 #. Maundy Thursday.
-#: holidays/countries/venezuela.py:55
+#: ./holidays/countries/venezuela.py:56
 msgid "Jueves Santo"
 msgstr "Великий четвер"
 
 #. Good Friday.
-#: holidays/countries/venezuela.py:58
+#: ./holidays/countries/venezuela.py:59
 msgid "Viernes Santo"
 msgstr "Страсна пʼятниця"
 
 #. Declaration of Independence.
-#: holidays/countries/venezuela.py:63
+#: ./holidays/countries/venezuela.py:64
 msgid "Declaración de la Independencia"
 msgstr "День проголошення незалежності"
 
 #. International Worker's Day.
-#: holidays/countries/venezuela.py:70
+#: ./holidays/countries/venezuela.py:69
 msgid "Dia Mundial del Trabajador"
 msgstr "Міжнародний день трудящих"
 
 #. Battle of Carabobo.
-#: holidays/countries/venezuela.py:75
+#: ./holidays/countries/venezuela.py:74
 msgid "Batalla de Carabobo"
 msgstr "День битви при Карабобо"
 
 #. Independence Day.
-#: holidays/countries/venezuela.py:80
+#: ./holidays/countries/venezuela.py:79
 msgid "Día de la Independencia"
 msgstr "День незалежності"
 
-#. Birth of Simon Bolivar.
-#: holidays/countries/venezuela.py:84
+#. Birthday of Simon Bolivar.
+#: ./holidays/countries/venezuela.py:83
 msgid "Natalicio de Simón Bolívar"
 msgstr "Річниця Сімона Болівара"
 
 #. Day of Indigenous Resistance.
-#: holidays/countries/venezuela.py:88
+#: ./holidays/countries/venezuela.py:87
 msgid "Día de la Resistencia Indígena"
 msgstr "День спротиву корінних народів"
 
 #. Columbus Day.
-#: holidays/countries/venezuela.py:93
+#: ./holidays/countries/venezuela.py:90
 msgid "Día de la Raza"
 msgstr "День Колумба"
 
 #. Unknown Holiday.
-#: holidays/countries/venezuela.py:99
+#: ./holidays/countries/venezuela.py:96
 msgid "Día Festivo Desconocido"
 msgstr "Невідоме свято"
 
 #. Christmas Eve.
-#: holidays/countries/venezuela.py:102
+#: ./holidays/countries/venezuela.py:99
 msgid "Nochebuena"
 msgstr "Святий вечір"
 
 #. Christmas Day.
-#: holidays/countries/venezuela.py:105
+#: ./holidays/countries/venezuela.py:102
 msgid "Día de Navidad"
 msgstr "Різдво Христове"
 
 #. New Year's Eve.
-#: holidays/countries/venezuela.py:108
+#: ./holidays/countries/venezuela.py:105
 msgid "Fiesta de Fin de Año"
 msgstr "Переддень Нового року"


Test patch:
diff --git a/tests/countries/test_france.py b/tests/countries/test_france.py
index f59061f6..13328ee9 100644
--- a/tests/countries/test_france.py
+++ b/tests/countries/test_france.py
@@ -9,83 +9,191 @@
 #  Website: https://github.com/dr-prodigy/python-holidays
 #  License: MIT (see LICENSE file)
 
-import unittest
-from datetime import date
+from holidays.countries.france import France, FR, FRA
+from tests.common import TestCase
 
-import holidays
 
+class TestFrance(TestCase):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass(France)
 
-class TestFrance(unittest.TestCase):
-    def setUp(self):
-        self.holidays = holidays.France()
-        self.prov_holidays = {
-            prov: holidays.FR(subdiv=prov)
-            for prov in holidays.FRA.subdivisions
-        }
+    def test_country_aliases(self):
+        self.assertCountryAliases(France, FR, FRA)
+
+    def test_pre_1802(self):
+        self.assertNoHoliday("1801-08-15", "1801-11-01", "1801-12-25")
 
     def test_2017(self):
-        self.assertIn(date(2017, 1, 1), self.holidays)
-        self.assertIn(date(2017, 4, 17), self.holidays)
-        self.assertIn(date(2017, 5, 1), self.holidays)
-        self.assertIn(date(2017, 5, 8), self.holidays)
-        self.assertIn(date(2017, 5, 25), self.holidays)
-        self.assertIn(date(2017, 6, 5), self.holidays)
-        self.assertIn(date(2017, 7, 14), self.holidays)
-
-    def test_others(self):
-        self.assertEqual(
-            self.holidays[date(1948, 5, 1)],
-            "Fête du Travail et de la Concorde sociale",
+        self.assertHolidayDates(
+            France(years=2017),
+            "2017-01-01",
+            "2017-04-17",
+            "2017-05-01",
+            "2017-05-08",
+            "2017-05-25",
+            "2017-06-05",
+            "2017-07-14",
+            "2017-08-15",
+            "2017-11-01",
+            "2017-11-11",
+            "2017-12-25",
+        )
+
+    def test_2022(self):
+        self.assertHolidayDates(
+            France(years=2022),
+            "2022-01-01",
+            "2022-04-18",
+            "2022-05-01",
+            "2022-05-08",
+            "2022-05-26",
+            "2022-06-06",
+            "2022-07-14",
+            "2022-08-15",
+            "2022-11-01",
+            "2022-11-11",
+            "2022-12-25",
+        )
+
+    def test_jour_de_lan(self):
+        self.assertHoliday("1811-01-01")
+        self.assertNoHoliday("1810-01-01")
+        self.assertNoHolidayName("Jour de l'an", France(years=1810))
+
+    def test_fete_du_travail(self):
+        name_old = "Fête du Travail et de la Concorde sociale"
+        name_new = "Fête du Travail"
+
+        self.assertHoliday("1919-05-01")
+        self.assertNoHoliday("1918-05-01")
+        self.assertNoHolidayName(name_old, France(years=1918))
+        self.assertNoHolidayName(name_new, France(years=range(1919, 1948)))
+        self.assertNoHolidayName(name_old, France(years=1948))
+        self.assertHolidaysName(name_old, "1919-05-01", "1947-05-01")
+        self.assertHolidaysName(name_new, "1948-05-01")
+
+    def test_fete_de_la_victoire(self):
+        self.assertHoliday(f"{year}-05-08" for year in range(1953, 1960))
+        self.assertHoliday("1982-05-08")
+        self.assertNoHoliday("1960-05-08", "1981-05-08")
+        self.assertNoHolidayName(
+            "Fête de la Victoire", France(years=range(1960, 1982))
         )
-        self.assertNotIn(date(1810, 1, 1), self.holidays)  # Jour de l'an
-        self.assertIn(date(1811, 1, 1), self.holidays)
 
-        self.assertNotIn(date(1879, 7, 14), self.holidays)  # Fete nationale
-        self.assertIn(date(1880, 7, 14), self.holidays)
+    def test_fete_nationale(self):
+        self.assertHoliday("1880-07-14")
+        self.assertNoHoliday("1879-07-14")
+        self.assertNoHolidayName("Fête nationale", France(years=1879))
+
+    def test_armistice(self):
+        self.assertHoliday("1918-11-11")
+        self.assertNoHoliday("1917-11-11")
+        self.assertNoHolidayName("Armistice", France(years=1917))
+
+    def test_lundi_de_pentecote(self):
+        self.assertNoHoliday(
+            "2005-05-16",
+            "2006-06-05",
+            "2007-05-28",
+        )
+        self.assertHoliday("2004-05-31", "2008-05-12")
 
     def test_alsace_moselle(self):
-        am_holidays = self.prov_holidays["Alsace-Moselle"]
-        self.assertIn(date(2017, 4, 14), am_holidays)
-        self.assertIn(date(2017, 12, 26), am_holidays)
+        self.assertHoliday(
+            France(subdiv="Alsace-Moselle"), "2017-04-14", "2017-12-26"
+        )
 
     def test_mayotte(self):
-        am_holidays = self.prov_holidays["Mayotte"]
-        self.assertIn(date(2017, 4, 27), am_holidays)
+        self.assertHoliday(France(subdiv="Mayotte"), "2017-04-27")
 
     def test_wallis_et_futuna(self):
-        am_holidays = self.prov_holidays["Wallis-et-Futuna"]
-        self.assertIn(date(2017, 4, 28), am_holidays)
-        self.assertIn(date(2017, 7, 29), am_holidays)
+        self.assertHoliday(
+            France(subdiv="Wallis-et-Futuna"), "2017-04-28", "2017-07-29"
+        )
 
     def test_martinique(self):
-        am_holidays = self.prov_holidays["Martinique"]
-        self.assertIn(date(2017, 5, 22), am_holidays)
+        self.assertHoliday(
+            France(subdiv="Martinique"),
+            "2017-04-14",
+            "2017-05-22",
+            "2017-07-21",
+        )
 
     def test_guadeloupe(self):
-        am_holidays = self.prov_holidays["Guadeloupe"]
-        self.assertIn(date(2017, 5, 27), am_holidays)
-        self.assertIn(date(2017, 7, 21), am_holidays)
+        self.assertHoliday(
+            France(subdiv="Guadeloupe"),
+            "2017-04-14",
+            "2017-05-27",
+            "2017-07-21",
+        )
+
+    def test_saint_martin(self):
+        self.assertHoliday(France(subdiv="Saint-Martin"), "2018-05-28")
+        self.assertNoHoliday(France(subdiv="Saint-Martin"), "2017-05-28")
+        self.assertNoHolidayName(
+            "Abolition de l'esclavage",
+            France(subdiv="Saint-Martin", years=2017),
+        )
 
     def test_guyane(self):
-        am_holidays = self.prov_holidays["Guyane"]
-        self.assertIn(date(2017, 6, 10), am_holidays)
+        self.assertHoliday(France(subdiv="Guyane"), "2017-06-10")
 
     def test_polynesie_francaise(self):
-        am_holidays = self.prov_holidays["Polynésie Française"]
-        self.assertIn(date(2017, 6, 29), am_holidays)
+        self.assertHoliday(
+            France(subdiv="Polynésie Française"),
+            "2017-03-05",
+            "2017-04-14",
+            "2017-06-29",
+        )
 
     def test_nouvelle_caledonie(self):
-        am_holidays = self.prov_holidays["Nouvelle-Calédonie"]
-        self.assertIn(date(2017, 9, 24), am_holidays)
+        self.assertHoliday(France(subdiv="Nouvelle-Calédonie"), "2017-09-24")
 
     def test_saint_barthelemy(self):
-        am_holidays = self.prov_holidays["Saint-Barthélémy"]
-        self.assertIn(date(2017, 10, 9), am_holidays)
+        self.assertHoliday(France(subdiv="Saint-Barthélémy"), "2017-10-09")
 
     def test_la_reunion(self):
-        am_holidays = self.prov_holidays["La Réunion"]
-        self.assertIn(date(2017, 12, 20), am_holidays)
+        self.assertHoliday(France(subdiv="La Réunion"), "2017-12-20")
+        self.assertNoHoliday(France(subdiv="La Réunion"), "1980-12-20")
+        self.assertNoHolidayName(
+            "Abolition de l'esclavage", France(subdiv="La Réunion", years=1980)
+        )
 
-    def test_pre_1802(self):
-        self.assertNotIn(date(1801, 8, 15), self.holidays)
-        self.assertNotIn(date(1801, 11, 1), self.holidays)
+    def test_l10n_default(self):
+        def run_tests(languages):
+            for language in languages:
+                mc = France(language=language)
+                self.assertEqual(mc["2022-01-01"], "Jour de l'an")
+                self.assertEqual(mc["2022-12-25"], "Noël")
+
+        run_tests((France.default_language, None, "invalid"))
+
+        self.set_language("en_US")
+        run_tests((France.default_language,))
+
+    def test_l10n_en_us(self):
+        en_us = "en_US"
+
+        fr = France(language=en_us)
+        self.assertEqual(fr["2022-01-01"], "New Year's Day")
+        self.assertEqual(fr["2022-12-25"], "Christmas Day")
+
+        self.set_language(en_us)
+        for language in (None, en_us, "invalid"):
+            fr = France(language=language)
+            self.assertEqual(fr["2022-01-01"], "New Year's Day")
+            self.assertEqual(fr["2022-12-25"], "Christmas Day")
+
+    def test_l10n_uk(self):
+        uk = "uk"
+
+        fr = France(language=uk)
+        self.assertEqual(fr["2022-01-01"], "Новий рік")
+        self.assertEqual(fr["2022-12-25"], "Різдво Христове")
+
+        self.set_language(uk)
+        for language in (None, uk, "invalid"):
+            fr = France(language=language)
+            self.assertEqual(fr["2022-01-01"], "Новий рік")
+            self.assertEqual(fr["2022-12-25"], "Різдво Христове")
diff --git a/tests/countries/test_south_korea.py b/tests/countries/test_south_korea.py
index 4ff31f60..ab8d6902 100644
--- a/tests/countries/test_south_korea.py
+++ b/tests/countries/test_south_korea.py
@@ -10,7 +10,6 @@
 #  License: MIT (see LICENSE file)
 
 import warnings
-from datetime import date
 
 from holidays.countries.south_korea import SouthKorea, KR, KOR, Korea
 from tests.common import TestCase
@@ -18,7 +17,7 @@ from tests.common import TestCase
 
 class TestSouthKorea(TestCase):
     @classmethod
-    def setUpClass(self):
+    def setUpClass(cls):
         super().setUpClass(SouthKorea)
 
     def test_country_aliases(self):
@@ -27,346 +26,302 @@ class TestSouthKorea(TestCase):
     def test_common(self):
         self.assertNonObservedHolidaysName("New Year's Day", "2019-01-01")
 
-        self.assertNotIn(date(1582, 10, 2), self.holidays)
-        self.assertNotIn(date(1582, 11, 14), self.holidays)
-
     def test_first_day_of_january(self):
-        for year in range(2006, 2021):
-            self.assertIn(self.holidays[date(year, 1, 1)], "New Year's Day")
+        self.assertHolidaysName(
+            "New Year's Day", (f"{year}-01-01" for year in range(2001, 2031))
+        )
 
     def test_lunar_new_year(self):
-        for year, month, day in [
-            (2006, 1, 28),
-            (2007, 2, 17),
-            (2010, 2, 13),
-            (2014, 1, 30),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "The day preceding of Lunar New Year's Day",
-            )
-
-        for year, month, day in [
-            (1916, 2, 4),
-            (1944, 1, 26),
-            (1954, 2, 4),
-            (1958, 2, 19),
-            (1966, 1, 22),
-            (1988, 2, 18),
-            (1997, 2, 8),
-            (2008, 2, 7),
-            (2009, 1, 26),
-            (2011, 2, 3),
-            (2012, 1, 23),
-            (2014, 1, 31),
-            (2015, 2, 19),
-            (2016, 2, 8),
-            (2017, 1, 28),
-            (2018, 2, 16),
-            (2019, 2, 5),
-            (2020, 1, 25),
-            (2027, 2, 7),
-            (2028, 1, 27),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Lunar New Year's Day",
-            )
-
-        for year, month, day in [
-            (2006, 1, 30),
-            (2007, 2, 19),
-            (2008, 2, 8),
-            (2009, 1, 27),
-            (2010, 2, 15),
-            (2011, 2, 4),
-            (2012, 1, 24),
-            (2013, 2, 11),
-            (2014, 2, 1),
-            (2015, 2, 20),
-            (2016, 2, 9),
-            (2018, 2, 17),
-            (2019, 2, 6),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "The second day of Lunar New Year's Day",
-            )
-
-        for year, month, day in [(2016, 2, 10), (2017, 1, 30), (2020, 1, 27)]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Alternative holiday of Lunar New Year's Day",
-            )
-
-        self.assertNotIn(date(2015, 2, 21), self.holidays)
-        self.assertNotIn(date(2015, 2, 7), self.holidays)
+        self.assertHolidaysName(
+            "The day preceding of Lunar New Year's Day",
+            "2014-01-30",
+            "2015-02-18",
+            "2016-02-07",
+            "2017-01-27",
+            "2018-02-15",
+            "2019-02-04",
+            "2020-01-24",
+            "2021-02-11",
+            "2022-01-31",
+            "2023-01-21",
+        )
+
+        self.assertHolidaysName(
+            "Lunar New Year's Day",
+            "1916-02-04",
+            "1944-01-26",
+            "1954-02-04",
+            "1958-02-19",
+            "1966-01-22",
+            "1988-02-18",
+            "1997-02-08",
+            "2008-02-07",
+            "2009-01-26",
+            "2010-02-14",
+            "2011-02-03",
+            "2012-01-23",
+            "2013-02-10",
+            "2014-01-31",
+            "2015-02-19",
+            "2016-02-08",
+            "2017-01-28",
+            "2018-02-16",
+            "2019-02-05",
+            "2020-01-25",
+            "2021-02-12",
+            "2022-02-01",
+            "2023-01-22",
+        )
+
+        self.assertHolidaysName(
+            "The second day of Lunar New Year's Day",
+            "2006-01-30",
+            "2007-02-19",
+            "2008-02-08",
+            "2009-01-27",
+            "2010-02-15",
+            "2011-02-04",
+            "2012-01-24",
+            "2013-02-11",
+            "2014-02-01",
+            "2015-02-20",
+            "2016-02-09",
+            "2017-01-29",
+            "2018-02-17",
+            "2019-02-06",
+            "2020-01-26",
+            "2021-02-13",
+            "2022-02-02",
+            "2023-01-23",
+        )
+
+        self.assertHolidaysName(
+            "Alternative holiday of Lunar New Year's Day",
+            "2016-02-10",
+            "2017-01-30",
+            "2020-01-27",
+            "2023-01-24",
+            "2024-02-12",
+            "2027-02-09",
+        )
+
+        self.assertNoHoliday("2015-02-07", "2015-02-21")
 
     def test_independence_movement_day(self):
-        for year, month, day in [
-            (2006, 3, 1),
-            (2022, 3, 1),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Independence Movement Day",
-            )
-
-        for year, month, day in [(2025, 3, 3)]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Alternative holiday of Independence Movement Day",
-            )
+        self.assertHolidaysName(
+            "Independence Movement Day",
+            (f"{year}-03-01" for year in range(2001, 2031)),
+        )
+
+        self.assertHolidaysName(
+            "Alternative holiday of Independence Movement Day",
+            "2025-03-03",
+            "2026-03-02",
+        )
 
     def test_tree_planting_day(self):
-        for year, month, day in [
-            (1949, 4, 5),
-            (2005, 4, 5),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Tree Planting Day",
-            )
-
-        for year, month, day in [
-            (1960, 4, 5),
-            (2006, 4, 5),
-        ]:
-            self.assertNotIn(date(year, month, day), self.holidays)
+        name = "Tree Planting Day"
+        self.assertHolidaysName(
+            name, (f"{year}-04-05" for year in range(2001, 2006))
+        )
+        self.assertNoHolidayName(name, SouthKorea(years=(1948, 1960, 2006)))
+        self.assertNoHoliday("1948-04-05", "1960-04-05", "2006-04-05")
 
     def test_childrens_day(self):
-        for year, month, day in [
-            (2015, 5, 5),
-            (2018, 5, 5),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Children's Day",
-            )
-
-        for year, month, day in [(2018, 5, 7), (2019, 5, 6)]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Alternative holiday of Children's Day",
-            )
-        for year, month, day in [(2025, 5, 6), (2044, 5, 6)]:
-            self.assertIn(
-                "Alternative holiday of Children's Day",
-                self.holidays[date(year, month, day)],
-            )
+        name = "Children's Day"
+        self.assertHolidaysName(
+            name,
+            (f"{year}-05-05" for year in range(2001, 2031)),
+        )
+        self.assertNoHolidayName(name, SouthKorea(years=1974))
+        self.assertNoHoliday("1974-05-05")
+
+        self.assertHolidaysName(
+            "Alternative holiday of Children's Day",
+            "2018-05-07",
+            "2019-05-06",
+            "2024-05-06",
+            "2025-05-06",
+            "2029-05-07",
+            "2030-05-06",
+        )
 
     def test_birthday_of_buddha(self):
-        name = "Birthday of the Buddha"
-        for year, month, day in [
-            (1931, 5, 25),
-            (1968, 5, 5),
-            (2010, 5, 21),
-            (2011, 5, 10),
-            (2012, 5, 28),
-            (2013, 5, 17),
-            (2014, 5, 6),
-            (2015, 5, 25),
-            (2016, 5, 14),
-            (2017, 5, 3),
-            (2018, 5, 22),
-            (2019, 5, 12),
-            (2020, 4, 30),
-            (2021, 5, 19),
-            (2022, 5, 8),
-            (2023, 5, 27),
-            (2024, 5, 15),
-            (2026, 5, 24),
-            (2027, 5, 13),
-            (2028, 5, 2),
-            (2029, 5, 20),
-            (2030, 5, 9),
-        ]:
-            self.assertEqual(self.holidays[date(year, month, day)], name)
-
-        for year, month, day in [(2001, 5, 1)]:
-            self.assertIn(
-                "Birthday of the Buddha",
-                self.holidays[date(year, month, day)],
-            )
+        self.assertHolidaysName(
+            "Birthday of the Buddha",
+            "2006-05-05",
+            "2007-05-24",
+            "2008-05-12",
+            "2009-05-02",
+            "2010-05-21",
+            "2011-05-10",
+            "2012-05-28",
+            "2013-05-17",
+            "2014-05-06",
+            "2015-05-25",
+            "2016-05-14",
+            "2017-05-03",
+            "2018-05-22",
+            "2019-05-12",
+            "2020-04-30",
+            "2021-05-19",
+            "2022-05-08",
+            "2023-05-27",
+        )
 
     def test_labour_day(self):
-        for year in [1948, 1993]:
-            self.assertIn("Labour Day", self.holidays[date(year, 3, 10)])
+        name = "Labour Day"
+        self.assertHolidaysName(
+            name,
+            (f"{year}-03-10" for year in range(1991, 1994)),
+        )
 
-        for year in [1994, 2023]:
-            self.assertIn("Labour Day", self.holidays[date(year, 5, 1)])
+        self.assertHolidaysName(
+            name,
+            (f"{year}-05-01" for year in range(2001, 2031)),
+        )
+        self.assertHolidaysName(name, "1994-05-01")
 
-        self.assertNotIn(date(1993, 5, 1), self.holidays)
-        self.assertNotIn(date(1994, 3, 10), self.holidays)
+        self.assertNoHoliday("1993-05-01", "1994-03-10")
 
     def test_memorial_day(self):
-        for year in [2006, 2022]:
-            self.assertEqual(self.holidays[date(year, 6, 6)], "Memorial Day")
+        self.assertHolidaysName(
+            "Memorial Day",
+            (f"{year}-06-06" for year in range(2001, 2031)),
+        )
 
     def test_constitution_day(self):
-        for year in [1948, 2007]:
-            self.assertEqual(
-                self.holidays[date(year, 7, 17)], "Constitution Day"
-            )
-        self.assertNotIn(date(1947, 7, 17), self.holidays)
-        self.assertNotIn(date(2008, 7, 17), self.holidays)
+        name = "Constitution Day"
+        self.assertHolidaysName(
+            name,
+            (f"{year}-07-17" for year in range(2001, 2008)),
+        )
+        self.assertHolidaysName(name, "1948-07-17")
+        self.assertNoHoliday("1947-07-17", "2008-07-17")
+        self.assertNoHolidayName(name, SouthKorea(years=(1947, 2008)))
 
     def test_liberation_day(self):
-        for year in [1945, 2020]:
-            self.assertEqual(
-                self.holidays[date(year, 8, 15)], "Liberation Day"
-            )
-        self.assertEqual(
-            self.holidays[date(2021, 8, 16)],
+        name = "Liberation Day"
+        self.assertHolidaysName(
+            name,
+            (f"{year}-08-15" for year in range(2001, 2031)),
+        )
+        self.assertHolidaysName(name, "1945-08-15")
+        self.assertNoHoliday("1944-08-15")
+        self.assertNoHolidayName(name, SouthKorea(years=1944))
+
+        self.assertHolidaysName(
             "Alternative holiday of Liberation Day",
+            "2021-08-16",
+            "2026-08-17",
+            "2027-08-16",
+            "2032-08-16",
         )
 
     def test_chuseok(self):
-        for year, month, day in [
-            (2010, 9, 21),
-            (2011, 9, 11),
-            (2012, 9, 29),
-            (2013, 9, 18),
-            (2014, 9, 7),
-            (2015, 9, 26),
-            (2016, 9, 14),
-            (2018, 9, 23),
-            (2019, 9, 12),
-            (2020, 9, 30),
-            (2021, 9, 20),
-            (2022, 9, 9),
-            (2023, 9, 28),
-            (2024, 9, 16),
-            (2025, 10, 5),
-            (2026, 9, 24),
-            (2027, 9, 14),
-            (2028, 10, 2),
-            (2029, 9, 21),
-            (2030, 9, 11),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "The day preceding of Chuseok",
-            )
-
-        for year, month, day in [(2017, 10, 3)]:
-            self.assertIn(
-                "The day preceding of Chuseok",
-                self.holidays[date(year, month, day)],
-            )
-
-        for year, month, day in [
-            (1942, 9, 25),
-            (1978, 9, 17),
-            (2010, 9, 22),
-            (2011, 9, 12),
-            (2012, 9, 30),
-            (2013, 9, 19),
-            (2014, 9, 8),
-            (2015, 9, 27),
-            (2016, 9, 15),
-            (2017, 10, 4),
-            (2018, 9, 24),
-            (2019, 9, 13),
-            (2020, 10, 1),
-            (2021, 9, 21),
-            (2022, 9, 10),
-            (2023, 9, 29),
-            (2024, 9, 17),
-            (2025, 10, 6),
-            (2026, 9, 25),
-            (2027, 9, 15),
-            (2029, 9, 22),
-            (2030, 9, 12),
-            (2040, 9, 21),
-        ]:
-            self.assertEqual(self.holidays[date(year, month, day)], "Chuseok")
-
-        for year, month, day in [(2028, 10, 3)]:
-            self.assertIn("Chuseok", self.holidays[date(year, month, day)])
-
-        for year, month, day in [
-            (2010, 9, 23),
-            (2011, 9, 13),
-            (2012, 10, 1),
-            (2013, 9, 20),
-            (2014, 9, 9),
-            (2015, 9, 28),
-            (2016, 9, 16),
-            (2017, 10, 5),
-            (2018, 9, 25),
-            (2019, 9, 14),
-            (2020, 10, 2),
-            (2021, 9, 22),
-            (2022, 9, 11),
-            (2023, 9, 30),
-            (2024, 9, 18),
-            (2025, 10, 7),
-            (2026, 9, 26),
-            (2027, 9, 16),
-            (2028, 10, 4),
-            (2029, 9, 23),
-            (2030, 9, 13),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "The second day of Chuseok",
-            )
-
-        for year, month, day in [
-            (2014, 9, 10),
-            (2015, 9, 29),
-            (2018, 9, 26),
-            (2022, 9, 12),
-            (2025, 10, 8),
-            (2029, 9, 24),
-        ]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Alternative holiday of Chuseok",
-            )
+        self.assertHolidaysName(
+            "The day preceding of Chuseok",
+            "2014-09-07",
+            "2015-09-26",
+            "2016-09-14",
+            "2017-10-03",
+            "2018-09-23",
+            "2019-09-12",
+            "2020-09-30",
+            "2021-09-20",
+            "2022-09-09",
+            "2023-09-28",
+        )
 
-    def test_national_foundation_day(self):
-        for year in [1951, 2049]:
-            self.assertIn(
-                "National Foundation Day",
-                self.holidays[date(year, 10, 3)],
-            )
-
-        for year, month, day in [(2021, 10, 4)]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Alternative holiday of National Foundation Day",
-            )
+        self.assertHolidaysName(
+            "Chuseok",
+            "1942-09-25",
+            "1978-09-17",
+            "2010-09-22",
+            "2011-09-12",
+            "2012-09-30",
+            "2013-09-19",
+            "2014-09-08",
+            "2015-09-27",
+            "2016-09-15",
+            "2017-10-04",
+            "2018-09-24",
+            "2019-09-13",
+            "2020-10-01",
+            "2021-09-21",
+            "2022-09-10",
+            "2023-09-29",
+        )
 
-    def test_hangeul_day(self):
-        for year in [1948, 1990]:
-            self.assertEqual(self.holidays[date(year, 10, 9)], "Hangeul Day")
+        self.assertHolidaysName(
+            "The second day of Chuseok",
+            "2010-09-23",
+            "2011-09-13",
+            "2012-10-01",
+            "2013-09-20",
+            "2014-09-09",
+            "2015-09-28",
+            "2016-09-16",
+            "2017-10-05",
+            "2018-09-25",
+            "2019-09-14",
+            "2020-10-02",
+            "2021-09-22",
+            "2022-09-11",
+            "2023-09-30",
+        )
 
-        for year in [2013, 2023]:
-            self.assertEqual(self.holidays[date(year, 10, 9)], "Hangeul Day")
+        self.assertHolidaysName(
+            "Alternative holiday of Chuseok",
+            "2014-09-10",
+            "2015-09-29",
+            "2018-09-26",
+            "2022-09-12",
+            "2025-10-08",
+            "2029-09-24",
+        )
 
-        for year in [1991, 2012]:
-            self.assertNotIn(date(year, 10, 9), self.holidays)
+    def test_national_foundation_day(self):
+        self.assertHolidaysName(
+            "National Foundation Day",
+            (f"{year}-10-03" for year in range(2001, 2031)),
+        )
 
-        for year, month, day in [(2021, 10, 11)]:
-            self.assertEqual(
-                self.holidays[date(year, month, day)],
-                "Alternative holiday of Hangeul Day",
-            )
+        self.assertHolidaysName(
+            "Alternative holiday of National Foundation Day",
+            "2021-10-04",
+            "2026-10-05",
+            "2027-10-04",
+        )
 
-    def test_christmas_day(self):
-        for year in [1948, 2050]:
-            self.assertEqual(
-                self.holidays[date(year, 12, 25)], "Christmas Day"
-            )
+    def test_hangeul_day(self):
+        name = "Hangeul Day"
+        self.assertHolidaysName(
+            name,
+            (f"{year}-10-09" for year in range(1985, 1991)),
+        )
+        self.assertHolidaysName(
+            name,
+            (f"{year}-10-09" for year in range(2013, 2031)),
+        )
+        self.assertNoHoliday("1991-10-09", "2012-10-09")
+        self.assertNoHolidayName(name, SouthKorea(years=(1991, 2012)))
+
+        self.assertHolidaysName(
+            "Alternative holiday of Hangeul Day",
+            "2021-10-11",
+            "2022-10-10",
+            "2027-10-11",
+        )
 
-    def test_years_range(self):
-        for year in [2006, 2021]:
-            self.assertIn(self.holidays[date(year, 1, 1)], "New Year's Day")
+    def test_christmas_day(self):
+        self.assertHolidaysName(
+            "Christmas Day",
+            (f"{year}-12-25" for year in range(2001, 2031)),
+        )
 
     def test_special_holidays(self):
-        self.assertIn("2020-08-17", self.holidays)
+        self.assertHoliday("2020-08-17")
 
     def test_korea_deprecation_warning(self):
         warnings.simplefilter("default")
diff --git a/tests/test_utils.py b/tests/test_utils.py
index d170235f..b15238a1 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -18,6 +18,8 @@ import pytest
 
 from holidays import utils
 
+PYTHON_VERSION = (3, 11)
+
 
 class TestCountryHolidays(unittest.TestCase):
     def setUp(self):
@@ -84,8 +86,10 @@ class TestFinancialHolidays(unittest.TestCase):
 class TestAllInSameYear(unittest.TestCase):
     """Test that only holidays in the year(s) requested are returned."""
 
+    years = set(range(1950, 2051))
+
     @pytest.mark.skipif(
-        sys.version_info < (3, 11),
+        sys.version_info < PYTHON_VERSION,
         reason="Run once on the latest Python version only",
     )
     @mock.patch("pathlib.Path.rglob", return_value=())
@@ -99,7 +103,37 @@ class TestAllInSameYear(unittest.TestCase):
         we only run it once on the latest Python version.
         """
         warnings.simplefilter("ignore")
+
         for country in utils.list_supported_countries():
-            for year in range(1950, 2051):
+            for year in self.years:
                 for holiday in utils.country_holidays(country, years=year):
                     self.assertEqual(holiday.year, year)
+        self.assertEqual(
+            self.years,
+            utils.country_holidays(country, years=self.years).years,
+        )
+
+    @pytest.mark.skipif(
+        sys.version_info < PYTHON_VERSION,
+        reason="Run once on the latest Python version only",
+    )
+    @mock.patch("pathlib.Path.rglob", return_value=())
+    def test_all_financial(self, unused_rglob_mock):
+        """
+        Only holidays in the year(s) requested should be returned. This
+        ensures that we avoid triggering a "RuntimeError: dictionary changed
+        size during iteration" error.
+
+        This is logic test and not a code compatibility test, so for expediency
+        we only run it once on the latest Python version.
+        """
+        warnings.simplefilter("ignore")
+
+        for market in utils.list_supported_financial():
+            for year in self.years:
+                for holiday in utils.financial_holidays(market, years=year):
+                    self.assertEqual(holiday.year, year)
+        self.assertEqual(
+            self.years,
+            utils.financial_holidays(market, years=self.years).years,
+        )