diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cea777e49ed76..a8dd47fd5bad7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1456,6 +1456,19 @@ 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/locales/en/_freeze_exemptions.json b/airflow-core/src/airflow/ui/public/i18n/locales/en/_freeze_exemptions.json new file mode 100644 index 0000000000000..43fcce7b0801f --- /dev/null +++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/_freeze_exemptions.json @@ -0,0 +1,12 @@ +{ + "admin": {}, + "assets": {}, + "browse": {}, + "common": {}, + "components": {}, + "dag": {}, + "dags": {}, + "dashboard": {}, + "hitl": {}, + "tasks": {} +} diff --git a/dev/i18n/check_translations_completeness.py b/dev/i18n/check_translations_completeness.py index 1ca6907423fc1..1435a829bc1c9 100755 --- a/dev/i18n/check_translations_completeness.py +++ b/dev/i18n/check_translations_completeness.py @@ -124,7 +124,12 @@ 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"] + locale=locale_dir.name, + files=[ + f.name + for f in locale_dir.iterdir() + if f.suffix == ".json" and f.name != "_freeze_exemptions.json" + ], ) for locale_dir in LOCALES_DIR.iterdir() if locale_dir.is_dir() diff --git a/scripts/ci/prek/check_default_language_freeze.py b/scripts/ci/prek/check_default_language_freeze.py new file mode 100755 index 0000000000000..10b4b4acd366f --- /dev/null +++ b/scripts/ci/prek/check_default_language_freeze.py @@ -0,0 +1,68 @@ +#!/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)