This is an automated email from the ASF dual-hosted git repository.
jasonliu 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 b5e546d36dc add SKILL.md and zh-CN agent skill instruction (#62059)
b5e546d36dc is described below
commit b5e546d36dce210f09dff7161783703818775326
Author: Kevin Yang <[email protected]>
AuthorDate: Thu Feb 19 10:01:41 2026 -0500
add SKILL.md and zh-CN agent skill instruction (#62059)
* add zh-CN agent skill instruction
resolve conflict in pre-commit, and soften wording in SKILL.md to instruct
agent take locale-specific guidelines with higher precedence
* add prek hook to list namespace file and update SKILL.md, remove i18n
policy reference, and fix table
* add shorten license to zh-CN.md
* soften the wording and instruct agent to take locale-specific instruction
with more precedence
* fix pre-commit hook add license, use SKILL instead of SKILLs
* fix insert license hook and add shorten license after yaml formatter
* fix markdown lint and update SKILL.md
---
.github/skills/airflow-translations/SKILL.md | 164 +++++++++++++++++++++
.../skills/airflow-translations/locales/zh-CN.md | 123 ++++++++++++++++
.pre-commit-config.yaml | 22 ++-
scripts/ci/prek/sync_translation_namespaces.py | 49 ++++++
4 files changed, 353 insertions(+), 5 deletions(-)
diff --git a/.github/skills/airflow-translations/SKILL.md
b/.github/skills/airflow-translations/SKILL.md
new file mode 100644
index 00000000000..9344d77ab32
--- /dev/null
+++ b/.github/skills/airflow-translations/SKILL.md
@@ -0,0 +1,164 @@
+---
+name: airflow-translations
+description: >
+ Translate, review, and maintain Apache Airflow i18n locale strings in JSON
+ translation files. Use when working with internationalization, localization,
+ or translation tasks in airflow-core/src/airflow/ui/public/i18n/locales/.
+ Covers Airflow terminology conventions and translation guidelines.
+license: Apache-2.0
+---
+<!-- SPDX-License-Identifier: Apache-2.0
https://www.apache.org/licenses/LICENSE-2.0 -->
+
+# Airflow Translations
+
+## Locale-Specific Guidelines
+
+Before translating, you **must** read the locale-specific guideline file for
+the target language. Locale files are located at `locales/<locale-name>.md`
+relative to this skill directory.
+
+Match the translation task to the correct locale file using the table below:
+
+| Locale Code | Language | Guideline File |
+| ----------- | ----------------------- | ------------------------------- |
+| `ar` | Arabic | [locales/ar.md](locales/ar.md) |
+| `ca` | Catalan | [locales/ca.md](locales/ca.md) |
+| `de` | German | [locales/de.md](locales/de.md) |
+| `el` | Greek | [locales/el.md](locales/el.md) |
+| `es` | Spanish | [locales/es.md](locales/es.md) |
+| `fr` | French | [locales/fr.md](locales/fr.md) |
+| `he` | Hebrew | [locales/he.md](locales/he.md) |
+| `hi` | Hindi | [locales/hi.md](locales/hi.md) |
+| `hu` | Hungarian | [locales/hu.md](locales/hu.md) |
+| `it` | Italian | [locales/it.md](locales/it.md) |
+| `ja` | Japanese | [locales/ja.md](locales/ja.md) |
+| `ko` | Korean | [locales/ko.md](locales/ko.md) |
+| `nl` | Dutch | [locales/nl.md](locales/nl.md) |
+| `pl` | Polish | [locales/pl.md](locales/pl.md) |
+| `pt` | Portuguese | [locales/pt.md](locales/pt.md) |
+| `th` | Thai | [locales/th.md](locales/th.md) |
+| `tr` | Turkish | [locales/tr.md](locales/tr.md) |
+| `zh-CN` | Simplified Chinese | [locales/zh-CN.md](locales/zh-CN.md)
|
+| `zh-TW` | Traditional Chinese | [locales/zh-TW.md](locales/zh-TW.md)
|
+
+If the target locale file does not yet exist, follow only the global rules in
this document.
+When a locale-specific guideline conflicts with a global rule, the
**locale-specific
+guideline takes precedence**.
+
+## Translation File Structure
+
+All translation files are JSON files located at:
+
+```
+airflow-core/src/airflow/ui/public/i18n/locales/<locale-name>/
+```
+
+Each locale directory contains namespace JSON files that mirror the English
+locale (`en/`). The English locale is the **default locale** and the primary
+source for all translations. The current namespace files are:
+
+<!-- START namespace-files, please keep comment here to allow auto update -->
+`admin.json`, `assets.json`, `browse.json`, `common.json`, `components.json`,
`dag.json`, `dags.json`, `dashboard.json`, `hitl.json`, `tasks.json`
+<!-- END namespace-files, please keep comment here to allow auto update -->
+
+## Translation Principles
+
+1. **Concise and clear** — Translations are used in UI elements (buttons,
+ labels, tooltips). Keep them short and suitable for constrained UI space.
+2. **Consistent** — Always use the same translated term for the same English
+ term. Refer to the glossary in your locale file.
+3. **Accurate** — Maintain the original meaning and intent.
+4. **Neutral tone** — Language should be polite and neutral.
+5. **Local conventions** — Respect date formats, number formatting, and
+ formal/informal tone as appropriate for the locale.
+
+## Do-Not-Translate Terms
+
+The following terms should remain in English by default. Locale-specific
+guidelines may override individual entries where established conventions exist:
+
+| Term | Reason
|
+| ------------------------ |
------------------------------------------------------------- |
+| `Airflow` | Product name
|
+| `Dag` / `Dags` | Airflow convention; always use `Dag`, never `DAG`
|
+| `XCom` / `XComs` | Airflow cross-communication mechanism name
|
+| `Provider` / `Providers` | Airflow extension package name
|
+| `REST API` | Standard technical term
|
+| `JSON` | Standard technical format name
|
+| `ID` | Universal abbreviation
|
+| `PID` | Unix process identifier
|
+| `UTC` | Time standard
|
+| `Schema` | Database term (keep unless locale has established
convention) |
+
+## Variable and Placeholder Handling
+
+Translation strings use the `{{variable}}` interpolation syntax (i18next
+format):
+
+- **Never translate** variable names inside `{{...}}`.
+- **Never remove** any `{{variable}}` placeholders.
+- **Reorder** placeholders as needed to match natural word order.
+- **Preserve** exact variable casing (e.g., `{{dagDisplayName}}`).
+
+## Plural Forms
+
+Airflow uses i18next plural suffixes (`_one`, `_other`, and optionally `_zero`,
+`_two`, `_few`, `_many`). Provide translations for **all** plural suffixes
+relevant to the language you provide translation for.
+
+## Hotkeys
+
+Hotkey values (e.g., `"hotkey": "e"`) are literal key bindings and should
+**not** be translated unless the locale-specific guideline specifies otherwise.
+
+## Translation Workflow
+
+1. **Read** the locale-specific guideline (`locales/<locale-name>.md`).
+2. **Identify** missing translations — use `--add-missing` to generate stubs
+ prefixed with `TODO: translate`:
+
+ ```bash
+ breeze ui check-translation-completeness --language <locale-name>
--add-missing
+ ```
+
+3. **Translate** the `TODO: translate` entries using this guide and the locale
+ glossary.
+4. **Remove** extra keys not present in the English source:
+
+ ```bash
+ breeze ui check-translation-completeness --language <locale-name>
--remove-extra
+ ```
+
+5. **Validate** completeness:
+
+ ```bash
+ breeze ui check-translation-completeness --language <locale-name>
+ ```
+
+## Common Airflow Terms
+
+The following terms appear frequently in the English source files. Each locale
+glossary should define consistent translations for them. The **Context** column
+disambiguates terms that may have different meanings outside of Airflow:
+
+| English Term | Context |
+| -------------------- | ---------------------------------------- |
+| Task | Unit of work in a Dag |
+| Task Instance | Single run of a Task |
+| Task Group | Logical grouping of Tasks |
+| Dag Run | Single execution of a Dag |
+| Operator | Type/class that defines a Task |
+| Trigger | Event or mechanism that starts a run |
+| Trigger Rule | Condition that determines Task execution |
+| Triggerer | Airflow component that handles triggers |
+| Schedule / Scheduler | Timing configuration / Airflow component |
+| Backfill | Retroactive execution of Dag Runs |
+| Asset | Data dependency tracked by Airflow |
+| Asset Event | Notification that an Asset was updated |
+| Connection | External system credentials |
+| Variable | Key-value configuration store |
+| Pool | Resource constraint mechanism |
+| Plugin | Extensibility mechanism |
+| Executor | Component that runs Tasks |
+| Queue | Execution queue for Tasks |
+| Audit Log | Record of system events |
diff --git a/.github/skills/airflow-translations/locales/zh-CN.md
b/.github/skills/airflow-translations/locales/zh-CN.md
new file mode 100644
index 00000000000..b17ec9785ef
--- /dev/null
+++ b/.github/skills/airflow-translations/locales/zh-CN.md
@@ -0,0 +1,123 @@
+<!-- SPDX-License-Identifier: Apache-2.0
https://www.apache.org/licenses/LICENSE-2.0 -->
+# Simplified Chinese (zh-CN)
+
+This document provides locale-specific instructions for translating English
+Airflow UI strings into Simplified Chinese. It inherits all global rules from
+the parent [SKILL.md](../SKILL.md).
+
+## Plural Forms
+
+Simplified Chinese **does not** distinguish between singular and plural forms.
+Use the **same translation** for both `_one` and `_other` suffixes:
+
+**English source:**
+
+```json
+"dagRun_one": "Dag Run",
+"dagRun_other": "Dag Runs"
+```
+
+**Correct** — identical for both:
+
+```json
+"dagRun_one": "Dag 执行",
+"dagRun_other": "Dag 执行"
+```
+
+## Spacing Rules
+
+Insert a **half-width space** between Chinese characters and adjacent
+English words, numbers, or symbols:
+
+**Correct:**
+
+```json
+"Dag 执行" // space between English and Chinese
+"最近 12 小时" // space around numbers
+"连接 ID" // space before abbreviation
+"{{count}} 个连接" // space after placeholder
+```
+
+**Incorrect:**
+
+```json
+"Dag执行" // missing space
+"最近12小时" // missing space around numbers
+```
+
+## Punctuation
+
+- Use **full-width** punctuation for Chinese sentences: `,` `。` `:` `?` `!`
+- Use **half-width** punctuation for content within English terms, JSON, or
+ code: `,` `.` `:` `?`
+- Use **full-width** parentheses for Chinese context: `(` `)`
+- Use **half-width** parentheses when wrapping English or variables: `(` `)`
+
+**Correct** — full-width for Chinese sentences:
+
+```json
+"confirmation": "确定要删除 {{resourceName}} 吗?此操作无法还原。"
+```
+
+**Correct** — half-width for English/variable context:
+
+```json
+"tooltip": "按下 {{hotkey}} 切换展开"
+```
+
+## Measure Words (量词)
+
+Chinese requires **measure words** (量词) between numbers and nouns. Use the
+appropriate measure word for each context:
+
+| Measure Word | Usage | Example |
+|---|---|---|
+| `个` | General objects (connections, variables, errors) | `删除 {{count}} 个连接` |
+| `次` | Occurrences (runs, executions, attempts) | `最近 {{count}} 次 Dag 执行` |
+| `项` | List items | `+ 其他 {{count}} 项` |
+
+## Tone and Formality
+
+- Use **neutral, slightly formal** register.
+- Use `您` (formal "you") in confirmations and destructive actions:
+ `"您即将删除以下连接:"`.
+- Avoid colloquial or overly casual expressions.
+- Keep translations **concise** — these are UI labels and button text.
+
+## Variable and Placeholder Examples
+
+Preserve all `{{variable}}` placeholders. Reorder as needed for natural Chinese
+word order:
+
+**English source:**
+
+```json
+"title": "Mark {{type}} as {{state}}"
+```
+
+**Correct** — placeholders preserved:
+
+```json
+"title": "标记 {{type}} 为 {{state}}"
+```
+
+**Incorrect** — variable names translated:
+
+```json
+"title": "标记 {{类型}} 为 {{状态}}"
+```
+
+## Terminology Reference
+
+The established zh-CN translations are defined in the existing locale files.
+Before translating, **read the existing zh-CN JSON files** to learn the
+established terminology:
+
+```
+airflow-core/src/airflow/ui/public/i18n/locales/zh-CN/
+```
+
+Use the translations found in these files as the authoritative glossary. When
+translating a term, check how it has been translated elsewhere in the locale
+to maintain consistency. If a term has not been translated yet, refer to the
+English source in `en/` and apply the rules in this document.
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 30d951bfb35..3cc8fcda7df 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -54,8 +54,9 @@ repos:
^\.github/.*\.md$|
^airflow-core/tests/system/README\.md$
exclude:
- (?x)
- .github/PULL_REQUEST_TEMPLATE\.md$
+ (?x)
+ .github/PULL_REQUEST_TEMPLATE\.md$|
+ .github/skills/
args:
- "--maxlevel"
- "2"
@@ -173,7 +174,7 @@ repos:
^\.claude/|
AGENTS\.md$|
CLAUDE\.md$|
- SKILLS\.md$|
+ SKILL\.md$|
^scripts/ci/license-templates/
- id: insert-license
name: Add short license for agentic Markdown files
@@ -189,9 +190,11 @@ repos:
^\.claude/|
AGENTS\.md$|
CLAUDE\.md$|
- SKILLS\.md$
+ SKILL\.md$
exclude:
- ^scripts/ci/license-templates/
+ (?x)
+ ^scripts/ci/license-templates/|
+ ^\.github/skills/airflow-translations/SKILL\.md$
- id: insert-license
name: Add license for all other files
args:
@@ -760,6 +763,15 @@ repos:
files:
^scripts/ci/docker-compose/integration-.*\.yml$|^contributing-docs/testing/integration_tests\.rst$
require_serial: true
pass_filenames: false
+ - id: sync-translation-namespaces
+ name: Sync translation namespace file list
+ entry: ./scripts/ci/prek/sync_translation_namespaces.py
+ language: python
+ files: >
+ (?x)
+ ^airflow-core/src/airflow/ui/public/i18n/locales/en/.*\.json$|
+ ^\.github/skills/airflow-translations/SKILL\.md$
+ pass_filenames: false
- id: update-pyproject-toml
name: Update Airflow's meta-package pyproject.toml
language: python
diff --git a/scripts/ci/prek/sync_translation_namespaces.py
b/scripts/ci/prek/sync_translation_namespaces.py
new file mode 100755
index 00000000000..192aab49fa2
--- /dev/null
+++ b/scripts/ci/prek/sync_translation_namespaces.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+# 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.
+"""Sync the translation namespace file list in SKILL.md with the English
locale directory."""
+
+from __future__ import annotations
+
+import sys
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).parent.resolve()))
+from common_prek_utils import AIRFLOW_ROOT_PATH, insert_documentation
+
+EN_LOCALE_DIR = (
+ AIRFLOW_ROOT_PATH / "airflow-core" / "src" / "airflow" / "ui" / "public" /
"i18n" / "locales" / "en"
+)
+SKILL_FILE = AIRFLOW_ROOT_PATH / ".github" / "skills" / "airflow-translations"
/ "SKILL.md"
+
+START_MARKER = "<!-- START namespace-files, please keep comment here to allow
auto update -->"
+END_MARKER = "<!-- END namespace-files, please keep comment here to allow auto
update -->"
+
+if __name__ == "__main__":
+ json_files = sorted(p.name for p in EN_LOCALE_DIR.glob("*.json"))
+ if not json_files:
+ print(f"No JSON files found in {EN_LOCALE_DIR}")
+ sys.exit(1)
+
+ formatted = ", ".join(f"`{f}`" for f in json_files) + "\n"
+ insert_documentation(
+ file_path=SKILL_FILE,
+ content=[formatted],
+ header=START_MARKER,
+ footer=END_MARKER,
+ extra_information="translation namespace file list",
+ )