This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 8d7cc721dad Implement simpler and faster freeze check for translations 
(#55154)
8d7cc721dad is described below

commit 8d7cc721dad900453d9068c399c9827f4610065d
Author: Jarek Potiuk <ja...@potiuk.com>
AuthorDate: Sat Sep 6 14:43:13 2025 +0200

    Implement simpler and faster freeze check for translations (#55154)
    
    This is follow-up after #55119 - implements the translation freeze
    quite a bit simpler and faster:
    
    * uses selective checks (fail fast)
    * does not check the dates (we will set the flag to False when freeze
      time passes
    * you can bypass the freeze with a label rather than having to
      commit exemption file
---
 .pre-commit-config.yaml                            |  13 --
 airflow-core/src/airflow/ui/public/i18n/README.md  | 219 +++++++++++++++------
 .../public/i18n/locales/ar/_freeze_exemptions.json |  22 ---
 .../airflow/ui/public/i18n/locales/ar/hitl.json    |   1 +
 .../public/i18n/locales/en/_freeze_exemptions.json |  18 --
 .../airflow/ui/public/i18n/locales/en/hitl.json    |   1 +
 .../public/i18n/locales/he/_freeze_exemptions.json |  18 --
 .../airflow/ui/public/i18n/locales/he/hitl.json    |   1 +
 .../i18n/locales/zh-TW/_freeze_exemptions.json     |  21 --
 .../airflow/ui/public/i18n/locales/zh-TW/hitl.json |   1 +
 .../pages/DagsList/DagsFilters/StateFilters.tsx    |   2 +-
 .../pages/HITLTaskInstances/HITLResponseForm.tsx   |   6 +-
 .../pages/HITLTaskInstances/HITLTaskInstances.tsx  |   2 +-
 .../airflow/ui/src/queries/useUpdateHITLDetail.ts  |   6 +-
 airflow-core/src/airflow/ui/src/utils/hitl.ts      |  11 +-
 .../src/airflow_breeze/utils/selective_checks.py   |  37 +++-
 dev/breeze/tests/test_selective_checks.py          |  35 ++++
 dev/i18n/check_translations_completeness.py        |   9 +-
 scripts/ci/prek/check_default_language_freeze.py   |  68 -------
 19 files changed, 245 insertions(+), 246 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 623ab537ab9..d04e48ce750 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1495,19 +1495,6 @@ repos:
         files: ^airflow-core/src/airflow/ui/public/i18n/locales/.*\.json$
         entry: ./scripts/ci/prek/check_i18n_json.py
         pass_filenames: false
-      - id: check-en-language-freeze
-        name: Check for Default language (English) freeze
-        description: Prevent changes to English translation files during the 
language freeze period (typically around release time; time is measured in UTC)
-        language: python
-        entry: ./scripts/ci/prek/check_default_language_freeze.py
-        args:
-          - --freeze-start-date
-          - "2025-09-01"
-          - --freeze-end-date
-          - "2025-09-09"
-        files: ^airflow-core/src/airflow/ui/public/i18n/locales/en/.*
-        exclude: 
^airflow-core/src/airflow/ui/public/i18n/locales/en/_freeze_exemptions\.json.*
-        pass_filenames: true
       - id: check-provider-yaml-valid
         name: Validate provider.yaml files
         entry: ./scripts/ci/prek/check_provider_yaml_files.py
diff --git a/airflow-core/src/airflow/ui/public/i18n/README.md 
b/airflow-core/src/airflow/ui/public/i18n/README.md
index e667ceb6023..cbfb353d385 100644
--- a/airflow-core/src/airflow/ui/public/i18n/README.md
+++ b/airflow-core/src/airflow/ui/public/i18n/README.md
@@ -21,8 +21,10 @@
 
 ## 1. Purpose & scope
 
-This document outlines the policy for internationalization (i18n) in Apache 
Airflow, detailing the lifecycle of translations within the project.
-This policy aims to avoid inconsistencies, maintenance issues, unclear 
ownership, and to ensure translation quality.
+This document outlines the policy for internationalization (i18n) in Apache 
Airflow, detailing the lifecycle
+of translations within the project.
+This policy aims to avoid inconsistencies, maintenance issues, unclear 
ownership, and to ensure translation
+quality.
 
 ### Scope
 
@@ -36,11 +38,15 @@ This policy applies to:
 - Release managers.
 
 > [!NOTE]
-> This policy currently applies only to changes made in Apache Airflow core, 
as i18n is not yet implemented for providers (including auth managers). When 
such support is added, this policy should be updated to reflect the expanded 
scope.
+> This policy currently applies only to changes made in Apache Airflow core, 
as i18n is not yet implemented
+> for providers (including auth managers). When such support is added, this 
policy should be updated to reflect
+> the expanded scope.
 
 ## 2. Definitions
 
-**Internationalization (i18n)** - The process of designing a software 
application so that it can be adapted to various languages and regions without 
engineering changes (see also the [Wikipedia 
article](https://en.wikipedia.org/wiki/Internationalization_and_localization)).
+**Internationalization (i18n)** - The process of designing a software 
application so that it can be adapted to
+various languages and regions without engineering changes (see also
+the [Wikipedia 
article](https://en.wikipedia.org/wiki/Internationalization_and_localization)).
 
 **Supported locale** - An officially accepted locale in 
`airflow-core/src/airflow/ui/public/i18n/locales`.
 
@@ -50,11 +56,13 @@ This policy applies to:
 
 **Code owner** - Apache Airflow committer with write permissions, listed in  
`.github/CODEOWNERS`.
 
-**Translation sponsor** - Apache Airflow committer supporting a non-committer 
translation owner (e.g., by communicating in the dev list or merging Pull 
Requests on their behalf).
+**Translation sponsor** - Apache Airflow committer supporting a non-committer 
translation owner (e.g., by
+communicating in the dev list or merging Pull Requests on their behalf).
 
 **Engaged translator** - Active contributor participating in translation 
without formal ownership.
 
-**Inactive translation/code owner** — A translation/code owner is considered 
inactive if they meet either of the following criteria:
+**Inactive translation/code owner** — A translation/code owner is considered 
inactive if they meet either of
+the following criteria:
 
 - The locale under their responsibility has remained incomplete for at least 2 
consecutive releases.
 - They have not participated in the Apache Airflow project for more than 12 
months.
@@ -63,15 +71,19 @@ This policy applies to:
 
 ## 3. Wording/Phrasing
 
-- Unless explicitly stated otherwise, all references to directories and files 
in this document pertain to those in the `main` branch.
-- Where emphasised by capital letters, the keywords "MUST", "MUST NOT", 
"REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
-"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 
interpreted as described in RFC 2119.
+- Unless explicitly stated otherwise, all references to directories and files 
in this document pertain to
+  those in the `main` branch.
+- Where emphasised by capital letters, the keywords "MUST", "MUST NOT", 
"REQUIRED", "SHALL", "SHALL NOT", "
+  SHOULD",
+  "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to 
be interpreted as described in
+  RFC 2119.
 
 ## 4. Roles & responsibilities
 
 ### 4.1. Translation owner
 
-- Translation owners are responsible for the following, in their assigned 
supported locale, according to the established quality standards and procedures 
stated below:
+- Translation owners are responsible for the following, in their assigned 
supported locale, according to the
+  established quality standards and procedures stated below:
   - Ensuring locale remains up-to-date with source code changes in the default 
locale.
   - Reviewing the language aspects of translation-related Pull Requests (PRs).
   - Resolving translation-related conflicts in PRs.
@@ -80,7 +92,8 @@ This policy applies to:
 
 ### 4.2. Code owner
 
-- Code owners are responsible for the following, in their assigned supported 
locale, according to the procedures stated below:
+- Code owners are responsible for the following, in their assigned supported 
locale, according to the
+  procedures stated below:
   - Reviewing the technical aspects of translation-related PRs (e.g., linting, 
formatting, etc.).
   - Merging translation-related PRs approved by the translation owner.
   - Resolving translation-related conflicts in PRs, when there's a conflict 
between translation owners.
@@ -91,7 +104,8 @@ This policy applies to:
 
 ### 4.3. Engaged translator
 
-- Engaged translators do not have any formal responsibilities, but they are 
encouraged to contribute to supported locales by:
+- Engaged translators do not have any formal responsibilities, but they are 
encouraged to contribute to
+  supported locales by:
   - Suggesting improvements.
   - Reviewing PRs.
   - Reporting issues or inconsistencies in translations.
@@ -99,32 +113,39 @@ This policy applies to:
   - Assisting translation owners with their tasks.
   - Being 3rd party reviewers for translation-related conflicts, when needed.
 - Engaged translators may be mentioned in a comment in the 
`.github/CODEOWNERS` file.
-- Suitable candidates for translation ownership may be suggested from engaged 
translators, upon their consent and approval by the procedure in section 6.1.
+- Suitable candidates for translation ownership may be suggested from engaged 
translators, upon their consent
+  and approval by the procedure in section 6.1.
 
 ## 5. Requirements
 
 ### 5.1. Translation ownership and code ownership
 
-- Each supported locale, except for the default language, MUST have at least 
one translation owner and at least one code owner assigned at all times, with 
these considerations:
+- Each supported locale, except for the default language, MUST have at least 
one translation owner and at
+  least one code owner assigned at all times, with these considerations:
   - Ownership for both roles MUST be approved according to the process 
discussed in section 6.1.
   - A single Apache Airflow committer MAY serve as both code owner and 
translation owner for the same locale.
-  - If none of the translation owners are code owners - there MAY be a 
translation sponsor assigned as a code owner.
+  - If none of the translation owners are code owners - there MAY be a 
translation sponsor assigned as a code
+    owner.
 - When the above is not met, steps mentioned in section 6.4 SHOULD be taken by 
the appropriate roles.
 
 > [!NOTE]
-> It is welcomed and desired to have more than one translation owner to enable 
peer reviews and provide coverage during absences.
+> It is welcomed and desired to have more than one translation owner to enable 
peer reviews and provide
+> coverage during absences.
 
 ### 5.2. Adding new locales
 
-To accept a new supported locale to the codebase, it MUST be approved through 
the process discussed in section 6.2.
+To accept a new supported locale to the codebase, it MUST be approved through 
the process discussed in section
+6.2.
 
 ### 5.3. Translation owners candidates
 
-- Translation owners candidates MUST declare and demonstrate a sufficient 
level of proficiency in the target language for translation purposes, including 
technical terminology (as detailed in section 6.5).
+- Translation owners candidates MUST declare and demonstrate a sufficient 
level of proficiency in the target
+  language for translation purposes, including technical terminology (as 
detailed in section 6.5).
 - Translation owners candidates, who are non-committers, MUST also meet the 
following criteria:
-     - They are active long-term contributors to the Apache Airflow project at 
the time of request.
-     - They have basic skills of working with Git and GitHub, as well as 
modifying JSON translation files within their target language.
-     - They have the support of an Apache Airflow committer who will act as a 
translation sponsor.
+  - They are active long-term contributors to the Apache Airflow project at 
the time of request.
+  - They have basic skills of working with Git and GitHub, as well as 
modifying JSON translation files within
+    their target language.
+  - They have the support of an Apache Airflow committer who will act as a 
translation sponsor.
 
 ### 5.4. Resolution of translation conflicts
 
@@ -132,33 +153,48 @@ Translation conflicts MUST be resolved according to the 
procedures outlined in s
 
 ### 5.5. Adding or rephrasing terms
 
-- When new terms are added to the default locale, all translation owners 
SHOULD create a follow-up PR to comply with the changes in their assigned 
locale.
-- When existing terms are rephrased in the default language (key is the same 
but value changed), all translation owners SHOULD do the same as above.
-- As the change of the default language might be un-noticed by translators 
(translation keys would stay valid) it is recommended to rename the translation 
key to force a detection of language gaps (translations would have 1 orphan 
(old) key and a missing (new) key).
-- In busy times with many parallel UI changes it is acceptable to batch 
changes together. Differences SHOULD be cleared prior to a release at the 
latest.
+- When new terms are added to the default locale, all translation owners 
SHOULD create a follow-up PR to
+  comply with the changes in their assigned locale.
+- When existing terms are rephrased in the default language (key is the same 
but value changed), all
+  translation owners SHOULD do the same as above.
+- As the change of the default language might be un-noticed by translators 
(translation keys would stay valid)
+  it is recommended to rename the translation key to force a detection of 
language gaps (translations would
+  have 1 orphan (old) key and a missing (new) key).
+- In busy times with many parallel UI changes it is acceptable to batch 
changes together. Differences SHOULD
+  be cleared prior to a release at the latest.
 
 > [!NOTE]
 > Tooling for detecting missing terms is available (see Tools & Resources 
 > section below).
 
 ### 5.6. Deprecating / refactoring terms
 
-- When existing terms are deprecated or refactored in the default locale (key 
renamed/relocated but value unchanged), **the contributor initiating the change 
holds responsible for updating all relevant locale files, and not any of the 
locale's owners**. When such available, automation through Breeze tooling 
SHOULD be used.
+- When existing terms are deprecated or refactored in the default locale (key 
renamed/relocated but value
+  unchanged), **the contributor initiating the change holds responsible for 
updating all relevant locale
+  files, and not any of the locale's owners**. When such available, automation 
through Breeze tooling SHOULD
+  be used.
 
 ### 5.7. Merging of translation-related Pull Requests (PRs)
 
 - Before merging any translation-related PR, it MUST be:
-   - Approved by a translation owner of the respective locale for language 
aspects, according to the standards and guidelines.
-     - When a translation owner initiates a PR and is the only one assigned to 
the locale, they SHOULD instead ask for approval from a third party (e.g., 
engaged translator), or if such is not available, declare their self-approval 
for the language aspects.
-   - Approved by a code owner, or another committer on their behalf, for 
technical aspects (e.g., linting, formatting, etc.).
-- Before merging a translation-related PR, the translation SHOULD be checked 
for completeness using the provided tools (see section 8).
+  - Approved by a translation owner of the respective locale for language 
aspects, according to the standards
+    and guidelines.
+    - When a translation owner initiates a PR and is the only one assigned to 
the locale, they SHOULD instead
+      ask for approval from a third party (e.g., engaged translator), or if 
such is not available, declare
+      their self-approval for the language aspects.
+  - Approved by a code owner, or another committer on their behalf, for 
technical aspects (e.g., linting,
+    formatting, etc.).
+- Before merging a translation-related PR, the translation SHOULD be checked 
for completeness using the
+  provided tools (see section 8).
 
 > [!WARNING]
-> In languages with different word order than English, or in Right-To-Left 
(RTL) languages, it is important to validate that the changes are properly 
reflected in the UI.
+> In languages with different word order than English, or in Right-To-Left 
(RTL) languages, it is important to
+> validate that the changes are properly reflected in the UI.
 > If they are not, please raise a GitHub issue or a PR for fixing it 
 > (separately from the translation PR).
 
 ### 5.8. Version release
 
-- Release managers MUST follow the requirements for releasing changes in 
supported locales defined in the [Release Management 
Policy](../../../../../../dev/README_RELEASE_AIRFLOW.md).
+- Release managers MUST follow the requirements for releasing changes in 
supported locales defined in
+  the [Release Management 
Policy](../../../../../../dev/README_RELEASE_AIRFLOW.md).
 
 ## 6. Procedures
 
@@ -167,22 +203,39 @@ Translation conflicts MUST be resolved according to the 
procedures outlined in s
 - The designated code owner, should post a thread to the dev list, requesting 
the approval of:
   - Introducing a new locale (including a link to the PR)
   - Translation owner(s) in the suggested locale for non committer candidates. 
(sponsored)
-- Within the thread, the code owner should demonstrate that the translation 
owner is suitable for the role, according to the requirements in section 5.3.
-- Approval of any translation owner who is not a committer requires at least 
one binding vote of 1 PMC member, and no objections from other committers/PMC.
+- Within the thread, the code owner should demonstrate that the translation 
owner is suitable for the role,
+  according to the requirements in section 5.3.
+- Approval of any translation owner who is not a committer requires at least 
one binding vote of 1 PMC member,
+  and no objections from other committers/PMC.
 - Approval of any translation owner who is also a code owner (committer) do 
not need to be voted on.
 
 ### 6.2. Approval of a new locale
 
 The following steps outline the process for approving a new locale to be added 
to the supported locales:
 
-- Creating a PR for adding the suggested locale to the codebase ([see 
example](https://github.com/apache/airflow/pull/51258/files)), which includes:
-    - The locale files (translated according to the guidelines) in the 
`airflow-core/src/airflow/ui/public/i18n/locales/<LOCALE_CODE>` directory, 
where `<LOCALE_CODE>` is the code of the language according to ISO 639-1 
standard (e.g., `fr` for French). Languages with regional variants should be 
handled in separate directories, where the name is suffixed with `-<VARIANT>`, 
and `<VARIANT>` is the variant that follows ISO 3166-1 or UN M.49 codes in 
lowercase (e.g., `zh-tw` for Taiwanese Mandarin).
-    - Making the required modifications in 
`airflow-core/src/airflow/ui/src/i18n/config.ts` ([see 
example](https://github.com/apache/airflow/pull/51258/files#diff-bfb4d5fafd26d206fb4a545a41ba303f33d15a479d21e0a726fd743bdf9717ff)).
-    - Changes to the `.github/CODEOWNERS` file to include the designated code 
owner(s) and translation owner(s) for the new locale, considering the following:
-        - A code owner who is also a translation sponsor should be indicated 
in a comment as well.
-        - If the PR author is neither eligible nor willing to become both of 
these roles, they should suggest relevant candidates for the missing role(s), 
or call for volunteers.
-- Applying the procedure in section 6.1. to approve the identities of the code 
owner(s) and the translation owner(s).
-- Only after the steps above are completed, the PR for the new translation may 
be merged (by the requirements in section 5.7).
+- Creating a PR for adding the suggested locale to the
+  codebase ([see 
example](https://github.com/apache/airflow/pull/51258/files)), which includes:
+  - The locale files (translated according to the guidelines) in the
+    `airflow-core/src/airflow/ui/public/i18n/locales/<LOCALE_CODE>` directory, 
where `<LOCALE_CODE>` is the
+    code of the language according to ISO 639-1 standard (e.g., `fr` for 
French). Languages with regional
+    variants should be handled in separate directories, where the name is 
suffixed with `-<VARIANT>`, and
+    `<VARIANT>` is the variant that follows ISO 3166-1 or UN M.49 codes in 
lowercase (e.g., `zh-tw` for
+    Taiwanese Mandarin).
+  - Making the required modifications in
+    `airflow-core/src/airflow/ui/src/i18n/config.ts` ([see 
example](https://github.com/apache/airflow/pull/51258/files#diff-bfb4d5fafd26d206fb4a545a41ba303f33d15a479d21e0a726fd743bdf9717ff)).
+  - Changes to the `.github/CODEOWNERS` file to include the designated code 
owner(s) and translation owner(s)
+    for the new locale, considering the following:
+    - A code owner who is also a translation sponsor should be indicated in a 
comment as well.
+    - If the PR author is neither eligible nor willing to become both of these 
roles, they should suggest
+      relevant candidates for the missing role(s), or call for volunteers.
+- Applying the procedure in section 6.1. to approve the identities of the code 
owner(s) and the translation
+  owner(s).
+- Only after the steps above are completed, the PR for the new translation may 
be merged (by the requirements
+  in section 5.7).
+- Translation owners and code owners for the new locale SHOULD add themselves 
to the `#i18n` channel of
+  Airflow slack - during freeze time this is where notification about new 
"last-minute" changes to translation
+  files will be published, also it's a great platform to collaborate and share 
internationalization tips and
+  tricks.
 
 ### 6.3. Translation conflict resolution
 
@@ -190,42 +243,53 @@ When a translation conflict arises in a locale-related 
PR, the following steps w
 
 - The involved parties should first try to reach a consensus through 
discussion in the PR.
 - If no consensus is reached, a translation owner may decide the outcome.
-- If multiple translation owners are involved and cannot reach consensus, the 
code owner will decide. If the code owner is sponsored,
-they should base their decision on a neutral source (e.g., a third-party 
opinion, translation tool, or LLM).
+- If multiple translation owners are involved and cannot reach consensus, the 
code owner will decide. If the
+  code owner is sponsored,
+  they should base their decision on a neutral source (e.g., a third-party 
opinion, translation tool, or LLM).
 - If the conflict is between code owners, a PMC member will be involved to 
resolve the conflict.
 
 ### 6.4. Relinquishing translation/code ownership
 
- - When a code owner asks to relinquish their role, or they become inactive, 
any another committer should:
-    - Raise a PR for removal of the previous code owner from the 
`.github/CODEOWNERS` file.
-    - Post a thread in the dev list that they step in as the code owner 
(either as a translation sponsor, or a translation owner according to steps 
discussed in section 6.1).
- - When a translation owner asks to relinquish their role, or they become 
inactive, and there are no other active translation owners, the code owner 
should:
-    - Raise a PR for removal of the translation owner from the 
`.github/CODEOWNERS` file.
-    - Post a thread in the dev list that they are looking for assigning 
someone else as the translation owner within 30 days.
-    - If a replacement is found within this time, they should be approved 
according to section 6.1.
-    - Otherwise, the code owner should raise a vote in the dev list for the 
removal of the translation from the codebase (7 days vote, PMC and committers 
votes are counted as binding).
+- When a code owner asks to relinquish their role, or they become inactive, 
any another committer should:
+  - Raise a PR for removal of the previous code owner from the 
`.github/CODEOWNERS` file.
+  - Post a thread in the dev list that they step in as the code owner (either 
as a translation sponsor, or a
+    translation owner according to steps discussed in section 6.1).
+- When a translation owner asks to relinquish their role, or they become 
inactive, and there are no other
+  active translation owners, the code owner should:
+  - Raise a PR for removal of the translation owner from the 
`.github/CODEOWNERS` file.
+  - Post a thread in the dev list that they are looking for assigning someone 
else as the translation owner
+    within 30 days.
+  - If a replacement is found within this time, they should be approved 
according to section 6.1.
+  - Otherwise, the code owner should raise a vote in the dev list for the 
removal of the translation from the
+    codebase (7 days vote, PMC and committers votes are counted as binding).
 
 ### 6.5 Demonstrating language proficiency
 
 Language proficiency for translation owners can be demonstrated through any of 
the following means:
 
-- Communications in open-source projects, social media, mailing lists, forums, 
or any other platforms in the target language.
+- Communications in open-source projects, social media, mailing lists, forums, 
or any other platforms in the
+  target language.
 - Direct communication with a proficient committer in the target language.
 - Official language certifications (this is not a mandatory requirement).
 
 ## 7. Standards & guidelines
 
 > [!CAUTION]
-> Usage of language that defies Apache Airflow's [code of 
conduct](http://airflow.apache.org/code-of-conduct/) is prohibited in any 
circumstances.
+> Usage of language that defies Apache Airflow's [code of 
conduct](http://airflow.apache.org/code-of-conduct/)
+> is prohibited in any circumstances.
 
-- Translations should be based on the default language (English). When 
translating a language that has already a similar translation supported
-(e.g., Portuguese vs. Spanish), the other language might be used as a 
reference, but still the default language (English) should be the primary 
source for translations.
+- Translations should be based on the default language (English). When 
translating a language that has already
+  a similar translation supported
+  (e.g., Portuguese vs. Spanish), the other language might be used as a 
reference, but still the default
+  language (English) should be the primary source for translations.
 - Translations should be accurate, maintaining original meaning and intent.
 - Translations should be complete, covering all terms and phrases in the 
default language.
 - Translation of technical terminology should be consistent (for example: Dag, 
Task, Operator, etc.).
 - Language should be polite and neutral in tone.
-- Local conventions should be considered (e.g., date formats, number 
formatting, formal vs. informal tone, etc.).
-  - In case that local conventions requires deviation from any of these 
guidelines, exceptions may be requested via PR or a thread in the dev list.
+- Local conventions should be considered (e.g., date formats, number 
formatting, formal vs. informal tone,
+  etc.).
+  - In case that local conventions requires deviation from any of these 
guidelines, exceptions may be
+    requested via PR or a thread in the dev list.
 - Formatting, placeholders, and variable substitutions must be preserved.
 
 ## 8. Tools & resources
@@ -258,14 +322,41 @@ uv run dev/i18n/check_translations_completeness.py 
--language <language_code> --
 > As of the time of writing, this policy is not enforced by any automated 
 > checks.
 > The following describe the desired future state of compliance and 
 > enforcement.
 
-- Automated checks SHOULD verify once in a while that all languages have 
corresponding entries for new terms in the default language. When translations 
are missing, relevant code owners should be notified.
-- Automated checks SHOULD allow a person doing translation to select the 
language and aid them in adding new translations so that they do not have to 
compare them manually. Possibly it can be done by adding `-–add-missing` to the 
verifying script that will add new entries with `TODO: translate: ENGLISH 
VERSION` and add prek hook to not allow such `TODO:` entries to be committed.
+- Automated checks SHOULD verify once in a while that all languages have 
corresponding entries for new terms
+  in the default language. When translations are missing, relevant code owners 
should be notified.
+- Automated checks SHOULD allow a person doing translation to select the 
language and aid them in adding new
+  translations so that they do not have to compare them manually. Possibly it 
can be done by adding
+  `-–add-missing` to the verifying script that will add new entries with 
`TODO: translate: ENGLISH VERSION`
+  and add prek hook to not allow such `TODO:` entries to be committed.
 
-## 10. Exceptions
+## 11. Freeze time
 
-If any exceptions to this policy are needed, they MUST be discussed and 
approved by voting in the dev list beforehand.
+Few weeks before a minor or major release, a freeze time for accepting new 
translations
+MUST be announced in the dev list, to allow time for testing and verification 
of translations.
 
-## 11. Review and updates
+During that freeze time there should be no changes applied to the English 
translation source files
+by default. When freeze time starts we set this variable in the
+`dev/breeze/src/airflow_breeze/utils/selective_checks.py` file:
+
+```python
+FAIL_WHEN_ENGLISH_TRANSLATION_CHANGED = True
+```
+
+This fails any attempt to change English translation files in a PR unless 
`allow translation change`
+label is applied to the PR. This allows to still fix critical issues in 
English translation files and make
+deliberate updates to it but avoids accidental changes.
+
+Any change in such English translation files during freeze time MUST be 
communicated in the
+`#18n` Slack channel - so that translators can be informed as early as 
possible about those translations
+being added.
+
+## 12. Exceptions
+
+If any exceptions to this policy are needed, they MUST be discussed and 
approved by voting in the dev list
+beforehand.
+
+## 13. Review and updates
 
 This policy will be reviewed and updated as needed to ensure it remains 
relevant and effective.
-Depending on the nature of the change, suggested updates might need to be 
discussed and approved by voting in the dev list.
+Depending on the nature of the change, suggested updates might need to be 
discussed and approved by voting in
+the dev list.
diff --git 
a/airflow-core/src/airflow/ui/public/i18n/locales/ar/_freeze_exemptions.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/ar/_freeze_exemptions.json
deleted file mode 100644
index 221fd9ad501..00000000000
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ar/_freeze_exemptions.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "admin": {},
-  "assets": {},
-  "browse": {},
-  "common": {},
-  "components": {},
-  "dag": {},
-  "dags": {},
-  "dashboard": {},
-  "hitl": {
-    "requiredActionCount_few": "إجراءات مطلوبة ({{count}})",
-    "requiredActionCount_many": "إجراءات مطلوبة ({{count}})",
-    "requiredActionCount_one": "إجراء مطلوب ({{count}})",
-    "requiredActionCount_other": "إجراءات مطلوبة ({{count}})",
-    "requiredActionCount_two": "إجرَاءان مطلوبان",
-    "requiredActionCount_zero": "لا توجد إجراءات مطلوبة",
-    "state": {
-      "noResponseReceived": "لم يتم استلام أي رد"
-    }
-  },
-  "tasks": {}
-}
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/ar/hitl.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/ar/hitl.json
index b110431f695..c971f452551 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/ar/hitl.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/ar/hitl.json
@@ -33,6 +33,7 @@
     "approvalRequired": "تتطلب موافقة",
     "choiceReceived": "تم استلام الاختيار",
     "choiceRequired": "يتطلب اختيارًا",
+    "noResponseReceived": "لم يتم استلام أي رد",
     "rejectionReceived": "تم استلام الرفض",
     "responseReceived": "تم استلام الاستجابة",
     "responseRequired": "تتطلب استجابة"
diff --git 
a/airflow-core/src/airflow/ui/public/i18n/locales/en/_freeze_exemptions.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/en/_freeze_exemptions.json
deleted file mode 100644
index d6f0e612043..00000000000
--- a/airflow-core/src/airflow/ui/public/i18n/locales/en/_freeze_exemptions.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "admin": {},
-  "assets": {},
-  "browse": {},
-  "common": {},
-  "components": {},
-  "dag": {},
-  "dags": {},
-  "dashboard": {},
-  "hitl": {
-    "requiredActionCount_one": "Required Action ({{count}})",
-    "requiredActionCount_other": "Required Actions ({{count}})",
-    "state": {
-      "noResponseReceived": "No Response Received"
-    }
-  },
-  "tasks": {}
-}
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/en/hitl.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/en/hitl.json
index 3abb51e0c4b..39e4c2251bf 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/en/hitl.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/hitl.json
@@ -25,6 +25,7 @@
     "approvalRequired": "Approval Required",
     "choiceReceived": "Choice Received",
     "choiceRequired": "Choice Required",
+    "noResponseReceived": "No Response Received",
     "rejectionReceived": "Rejection Received",
     "responseReceived": "Response Received",
     "responseRequired": "Response Required"
diff --git 
a/airflow-core/src/airflow/ui/public/i18n/locales/he/_freeze_exemptions.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/he/_freeze_exemptions.json
deleted file mode 100644
index 1b20d39f368..00000000000
--- a/airflow-core/src/airflow/ui/public/i18n/locales/he/_freeze_exemptions.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "admin": {},
-  "assets": {},
-  "browse": {},
-  "common": {},
-  "components": {},
-  "dag": {},
-  "dags": {},
-  "dashboard": {},
-  "hitl": {
-    "requiredActionCount_one": "פעולה נדרשת ({{count}})",
-    "requiredActionCount_other": "פעולות נדרשות ({{count}})",
-    "state": {
-      "noResponseReceived": "לא התקבלה תגובה"
-    }
-  },
-  "tasks": {}
-}
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/he/hitl.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/he/hitl.json
index 89a7af3203c..588f6c9fcc5 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/he/hitl.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/he/hitl.json
@@ -25,6 +25,7 @@
     "approvalRequired": "נדרש אישור",
     "choiceReceived": "הבחירה התקבלה",
     "choiceRequired": "נדרשת בחירה",
+    "noResponseReceived": "לא התקבלה תגובה",
     "rejectionReceived": "הדחייה התקבלה",
     "responseReceived": "התגובה התקבלה",
     "responseRequired": "נדרשת תגובה"
diff --git 
a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/_freeze_exemptions.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/_freeze_exemptions.json
deleted file mode 100644
index 86b26aaa64b..00000000000
--- 
a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/_freeze_exemptions.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-  "admin": {},
-  "assets": {},
-  "browse": {},
-  "common": {},
-  "components": {},
-  "dag": {},
-  "dags": {},
-  "dashboard": {},
-  "hitl": {
-    "filters": {
-      "response": {
-        "received": "已回應"
-      }
-    },
-    "state": {
-      "noResponseReceived": "未收到回應"
-    }
-  },
-  "tasks": {}
-}
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/hitl.json 
b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/hitl.json
index 47e12b27aa5..b84aef9ee89 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/hitl.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/zh-TW/hitl.json
@@ -23,6 +23,7 @@
     "approvalRequired": "需要核准",
     "choiceReceived": "已選擇",
     "choiceRequired": "需要選擇",
+    "noResponseReceived": "未收到回應",
     "rejectionReceived": "已拒絕",
     "responseReceived": "已回應",
     "responseRequired": "需要回應"
diff --git 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/StateFilters.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/StateFilters.tsx
index df9d1df5e04..3bda2ba98fe 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/StateFilters.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsFilters/StateFilters.tsx
@@ -47,7 +47,7 @@ export const StateFilters = ({
   return (
     <HStack>
       <QuickFilterButton isActive={isAll} onClick={onStateChange} value="all">
-        {translate("filters.paused.all")}
+        {translate("dags:filters.paused.all")}
       </QuickFilterButton>
       <QuickFilterButton
         data-testid="dags-failed-filter"
diff --git 
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx 
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx
index 38f3cdd7c44..1f45dae5fc7 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx
@@ -50,7 +50,7 @@ const isHighlightOption = (option: string, hitlDetail: 
HITLDetail, preloadedHITL
 };
 
 export const HITLResponseForm = ({ hitlDetail }: HITLResponseFormProps) => {
-  const { t: translate } = useTranslation();
+  const { t: translate } = useTranslation("hitl");
   const [errors, setErrors] = useState<boolean>(false);
   const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
   const { paramsDict } = useParamStore("hitl");
@@ -96,7 +96,7 @@ export const HITLResponseForm = ({ hitlDetail }: 
HITLResponseFormProps) => {
     <Box mt={4}>
       {hitlDetail.response_received ? (
         <Text color="fg.muted" fontSize="sm">
-          {translate("hitl:response.received")}
+          {translate("response.received")}
           <Time datetime={hitlDetail.response_at} format="YYYY-MM-DD, 
HH:mm:ss" />
         </Text>
       ) : undefined}
@@ -144,7 +144,7 @@ export const HITLResponseForm = ({ hitlDetail }: 
HITLResponseFormProps) => {
               loading={isSubmitting}
               onClick={() => handleSubmit()}
             >
-              <FiSend /> {translate("hitl:response.respond")}
+              <FiSend /> {translate("response.respond")}
             </Button>
           )}
         </HStack>
diff --git 
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx 
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
index 666e679d5b6..80481a86e9f 100644
--- 
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
+++ 
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
@@ -114,7 +114,7 @@ const taskInstanceColumns = ({
 ];
 
 export const HITLTaskInstances = () => {
-  const { t: translate } = useTranslation(["hitl", "_freeze_exemptions"]);
+  const { t: translate } = useTranslation("hitl");
   const { dagId, runId, taskId } = useParams();
   const [searchParams, setSearchParams] = useSearchParams();
   const { setTableURLState, tableURLState } = useTableURLState();
diff --git a/airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts 
b/airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts
index 18d26ad80a5..03d3246cc6b 100644
--- a/airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts
+++ b/airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts
@@ -45,7 +45,7 @@ export const useUpdateHITLDetail = ({
 }) => {
   const queryClient = useQueryClient();
   const [error, setError] = useState<unknown>(undefined);
-  const { t: translate } = useTranslation(["common", "hitl"]);
+  const { t: translate } = useTranslation("hitl");
   const onSuccess = async () => {
     const queryKeys = [
       UseDagRunServiceGetDagRunKeyFn({ dagId, dagRunId }),
@@ -59,7 +59,7 @@ export const useUpdateHITLDetail = ({
     await Promise.all(queryKeys.map((key) => queryClient.invalidateQueries({ 
queryKey: key })));
 
     toaster.create({
-      title: translate("hitl:response.success", { taskId }),
+      title: translate("response.success", { taskId }),
       type: "success",
     });
   };
@@ -67,7 +67,7 @@ export const useUpdateHITLDetail = ({
   const onError = (_error: Error) => {
     toaster.create({
       description: _error.message,
-      title: translate("hitl:response.error"),
+      title: translate("response.error"),
       type: "error",
     });
   };
diff --git a/airflow-core/src/airflow/ui/src/utils/hitl.ts 
b/airflow-core/src/airflow/ui/src/utils/hitl.ts
index 06d4fdc24ab..7d38a09374d 100644
--- a/airflow-core/src/airflow/ui/src/utils/hitl.ts
+++ b/airflow-core/src/airflow/ui/src/utils/hitl.ts
@@ -79,10 +79,10 @@ export const getHITLParamsDict = (
 
   if (shouldRenderOptionDropdown || hitlDetail.options.length > 4 || 
hitlDetail.multiple) {
     paramsDict.chosen_options = {
-      description: translate("hitl:response.optionsDescription"),
+      description: translate("response.optionsDescription"),
       schema: {
         const: undefined,
-        description_md: translate("hitl:response.optionsDescription"),
+        description_md: translate("response.optionsDescription"),
         enum: hitlDetail.options.length > 0 ? hitlDetail.options : undefined,
         examples: undefined,
         format: undefined,
@@ -92,7 +92,7 @@ export const getHITLParamsDict = (
         minimum: undefined,
         minLength: undefined,
         section: undefined,
-        title: translate("hitl:response.optionsLabel"),
+        title: translate("response.optionsLabel"),
         type: hitlDetail.multiple ? "array" : "string",
         values_display: undefined,
       },
@@ -180,8 +180,7 @@ export const getHITLState = (translate: TFunction, 
hitlDetail: HITLDetail) => {
   let stateType: [string, string] = ["responseRequired", "responseReceived"];
 
   if (!responseReceived && isNotDeferred) {
-    // TODO: update this after unfreezing hitl.json
-    return translate("_freeze_exemptions:hitl.state.noResponseReceived");
+    return translate("state.noResponseReceived");
   }
 
   if (options.length === 2 && options.includes("Approve") && 
options.includes("Reject")) {
@@ -197,5 +196,5 @@ export const getHITLState = (translate: TFunction, 
hitlDetail: HITLDetail) => {
 
   const [required, received] = stateType;
 
-  return translate(`hitl:state.${responseReceived ? received : required}`);
+  return translate(`state.${responseReceived ? received : required}`);
 };
diff --git a/dev/breeze/src/airflow_breeze/utils/selective_checks.py 
b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
index fdfa6bbf384..88543d0426f 100644
--- a/dev/breeze/src/airflow_breeze/utils/selective_checks.py
+++ b/dev/breeze/src/airflow_breeze/utils/selective_checks.py
@@ -85,13 +85,16 @@ LOG_WITHOUT_MOCK_IN_TESTS_EXCEPTION_LABEL = "log exception"
 NON_COMMITTER_BUILD_LABEL = "non committer build"
 UPGRADE_TO_NEWER_DEPENDENCIES_LABEL = "upgrade to newer dependencies"
 USE_PUBLIC_RUNNERS_LABEL = "use public runners"
-
+ALLOW_TRANSACTION_CHANGE_LABEL = "allow translation change"
 ALL_CI_SELECTIVE_TEST_TYPES = "API Always CLI Core Other Serialization"
 
 ALL_PROVIDERS_SELECTIVE_TEST_TYPES = (
     "Providers[-amazon,google,standard] Providers[amazon] Providers[google] 
Providers[standard]"
 )
 
+# Set to True to enter a translation freeze period. Set to False to exit a 
translation freeze period.
+FAIL_WHEN_ENGLISH_TRANSLATION_CHANGED = True
+
 
 class FileGroupForCi(Enum):
     ENVIRONMENT_FILES = "environment_files"
@@ -125,6 +128,7 @@ class FileGroupForCi(Enum):
     ASSET_FILES = "asset_files"
     UNIT_TEST_FILES = "unit_test_files"
     DEVEL_TOML_FILES = "devel_toml_files"
+    UI_ENGLISH_TRANSLATION_FILES = "ui_english_translation_files"
 
 
 class AllProvidersSentinel:
@@ -299,6 +303,9 @@ CI_FILE_GROUP_MATCHES: HashableDict[FileGroupForCi] = 
HashableDict(
         FileGroupForCi.DEVEL_TOML_FILES: [
             r"^devel-common/pyproject\.toml$",
         ],
+        FileGroupForCi.UI_ENGLISH_TRANSLATION_FILES: [
+            r"^airflow-core/src/airflow/ui/public/i18n/locales/en/.*\.json$",
+        ],
     }
 )
 
@@ -1518,3 +1525,31 @@ class SelectiveChecks:
     @cached_property
     def shared_distributions_as_json(self):
         return json.dumps([file.name for file in (AIRFLOW_ROOT_PATH / 
"shared").iterdir() if file.is_dir()])
+
+    @cached_property
+    def ui_english_translation_changed(self) -> bool:
+        _translation_changed = bool(
+            self._matching_files(
+                FileGroupForCi.UI_ENGLISH_TRANSLATION_FILES,
+                CI_FILE_GROUP_MATCHES,
+            )
+        )
+        if FAIL_WHEN_ENGLISH_TRANSLATION_CHANGED and _translation_changed:
+            if ALLOW_TRANSACTION_CHANGE_LABEL in self._pr_labels:
+                get_console().print(
+                    "[warning]The 'allow translation change' label is set and 
English "
+                    "translation files changed. Bypassing the freeze period."
+                )
+                return True
+            get_console().print(
+                "[error]English translation changed but we are in a period of 
translation"
+                "freeze and label to allow it ('allow translation change') is 
not set"
+            )
+            get_console().print()
+            get_console().print(
+                "[warning]To allow translation change, please set the label "
+                "'allow translation change' on the PR, but this has to be 
communicated "
+                "and agreed to at the #i18n channel in slack"
+            )
+            sys.exit(1)
+        return _translation_changed
diff --git a/dev/breeze/tests/test_selective_checks.py 
b/dev/breeze/tests/test_selective_checks.py
index 4ec74cf0d38..a5deacf8816 100644
--- a/dev/breeze/tests/test_selective_checks.py
+++ b/dev/breeze/tests/test_selective_checks.py
@@ -2659,3 +2659,38 @@ def test_is_log_mocked_in_the_tests_not_fail_with_label(
         default_branch="main",
     )
     assert selective_checks.is_log_mocked_in_the_tests
+
+
+def test_ui_english_translation_changed_false():
+    selective_checks = SelectiveChecks(
+        files=("README.md",),
+        commit_ref=NEUTRAL_COMMIT,
+        pr_labels=(),
+        github_event=GithubEvents.PULL_REQUEST,
+        default_branch="main",
+    )
+    assert selective_checks.ui_english_translation_changed is False
+
+
+def test_ui_english_translation_changed_fail_on_change():
+    translation_file = 
"airflow-core/src/airflow/ui/public/i18n/locales/en/some_file.json"
+    with pytest.raises(SystemExit):
+        SelectiveChecks(
+            files=(translation_file,),
+            commit_ref=NEUTRAL_COMMIT,
+            pr_labels=(),
+            github_event=GithubEvents.PULL_REQUEST,
+            default_branch="main",
+        ).ui_english_translation_changed
+
+
+def test_ui_english_translation_changed_allowed_with_label():
+    translation_file = 
"airflow-core/src/airflow/ui/public/i18n/locales/en/some_file.json"
+    selective_checks = SelectiveChecks(
+        files=(translation_file,),
+        commit_ref=NEUTRAL_COMMIT,
+        pr_labels=("allow translation change",),
+        github_event=GithubEvents.PULL_REQUEST,
+        default_branch="main",
+    )
+    assert selective_checks.ui_english_translation_changed is True
diff --git a/dev/i18n/check_translations_completeness.py 
b/dev/i18n/check_translations_completeness.py
index f2a0b6a75ae..eab59723def 100755
--- a/dev/i18n/check_translations_completeness.py
+++ b/dev/i18n/check_translations_completeness.py
@@ -125,12 +125,7 @@ def expand_plural_keys(keys: set[str], lang: str) -> 
set[str]:
 def get_locale_files() -> list[LocaleFiles]:
     return [
         LocaleFiles(
-            locale=locale_dir.name,
-            files=[
-                f.name
-                for f in locale_dir.iterdir()
-                if f.suffix == ".json" and f.name != "_freeze_exemptions.json"
-            ],
+            locale=locale_dir.name, files=[f.name for f in 
locale_dir.iterdir() if f.suffix == ".json"]
         )
         for locale_dir in LOCALES_DIR.iterdir()
         if locale_dir.is_dir()
@@ -389,7 +384,7 @@ def print_translation_progress(console, locale_files, 
missing_counts, summary):
 
         # check missing translation files
         en_root = LOCALES_DIR / "en"
-        if diffs := set(os.listdir(en_root)) - {"_freeze_exemptions.json"} - 
set(all_files):
+        if diffs := set(os.listdir(en_root)) - set(all_files):
             for diff in diffs:
                 with open(en_root / diff) as f:
                     en_data = json.load(f)
diff --git a/scripts/ci/prek/check_default_language_freeze.py 
b/scripts/ci/prek/check_default_language_freeze.py
deleted file mode 100755
index 10b4b4acd36..00000000000
--- a/scripts/ci/prek/check_default_language_freeze.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-from __future__ import annotations
-
-import argparse
-import sys
-from datetime import datetime, timedelta, timezone
-from subprocess import run
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser(
-        description="Check for language freeze period and prevent changes to 
specified files."
-    )
-    parser.add_argument("--freeze-start-date", required=True, help="Start date 
of the freeze (YYYY-MM-DD)")
-    parser.add_argument("--freeze-end-date", required=True, help="End date of 
the freeze (YYYY-MM-DD)")
-    parser.add_argument("files", nargs="*", help="Files to check.")
-    args = parser.parse_args()
-
-    freeze_start = None
-    freeze_end = None
-    try:
-        freeze_start = datetime.strptime(args.freeze_start_date, 
"%Y-%m-%d").date()
-        freeze_end = datetime.strptime(args.freeze_end_date, "%Y-%m-%d").date()
-    except ValueError as e:
-        print(f"Error: Invalid date format in pre-commit config. {e}", 
file=sys.stderr)
-        sys.exit(1)
-
-    today = datetime.now(timezone(timedelta(hours=-12))).date()
-
-    if freeze_start <= today <= freeze_end:
-        changed_files = [
-            f for f in args.files if run(["git", "diff", "--cached", 
"--quiet", "--", f]).returncode != 0
-        ]
-        if changed_files:
-            print(
-                f"Error: English language freeze is active from 
{args.freeze_start_date} to "
-                f"{args.freeze_end_date}.",
-                file=sys.stderr,
-            )
-            print(
-                "Changes to English translation files (except for 
_freeze_exemptions.json) are not allowed during this period.",
-                file=sys.stderr,
-            )
-            print(
-                "You may instead add the changes to _freeze_exemptions.json, 
and by the end of the freeze period, we will merge them back to the original 
files.",
-                file=sys.stderr,
-            )
-            print("The following files have staged changes:", file=sys.stderr)
-            for file_path in changed_files:
-                print(f"  - {file_path}", file=sys.stderr)
-            sys.exit(1)
-
-    sys.exit(0)

Reply via email to