Apache Airflow UI 波兰语本地化实战:复数形式、格变化与翻译规范全解析
本文以 Airflow 仓库中波兰语翻译指南(pl.md)为核心,系统讲解将 Airflow UI 英文界面字符串翻译成波兰语时必须遵守的规则:四种复数形式的选择逻辑、名词格变化与性一致、占位符与术语的处理边界,并结合 PLURAL_SUFFIXES 配置与 pl/ 目录下的实际 JSON 翻译文件,说明这些规则在完整性检查工具链中是如何被校验的。读完后,你可以独立完成 Airflow 界面某一批波兰语字符串的翻译,并使其通过 breeze ui check-translation-completeness 的完整性验证。
1. 文档定位:波兰语指南在整个 i18n 体系中的角色
pl.md 位于 .agents/skills/airflow-translations/locales/ 目录下,是 Airflow 翻译技能(skill)为各语言编写的“本地化指南”之一,姊妹文件还包括 de.md、zh-CN.md 等 18 个语言版本。
该指南自身的定位在文件开头就写得很明确:它提供的是波兰语专属规则,其余全局规则(保留英文的术语清单、占位符规范、复数后缀机制等)一律继承自父级技能文档 SKILL.md。换言之,pl.md 只负责回答“哪些规则在波兰语下有特殊处理”,而 Airflow 完整的 UI 国际化政策(默认语言为英文、完整度阈值、翻译责任人制度等)定义在 i18n README 中。
按 SKILL.md 的工作流,波兰语翻译有两种场景:
- 新增翻译:
locales/pl/目录不存在时,需要先创建目录、更新三处配置(config.ts 的supportedLanguages数组、ui_commands.py 的PLURAL_SUFFIXES字典、.github/boring-cyborg.yml的标签规则),再运行breeze ui check-translation-completeness --language pl --add-missing生成带TODO: translate:桩的 JSON 文件; - 更新既有翻译:先读 pl.md 建立术语与格式规则,再读现有 JSON 学习已确立的译法,然后用同一命令检查缺口,配合
--add-missing(补桩)与--remove-unused(删无用键)完成维护。
当前仓库中波兰语已经是正式支持的本地化:config.ts 的 supportedLanguages 数组中包含 { code: "pl", name: "Polski" },ui_commands.py 中也登记了 "pl": ["_one", "_few", "_many", "_other"]。因此对 pl 而言,实战中绝大多数工作是第二种场景——更新既有翻译。
每个语言目录下包含 10 个命名空间 JSON 文件(admin.json、assets.json、browse.json、common.json、components.json、dag.json、dags.json、dashboard.json、hitl.json、tasks.json),结构与英文目录 en/ 一一对应。英文是默认语言,也是所有翻译的源语言;若某键在波兰语中缺失,运行时将回退到英文。
2. 四种复数形式:波兰语最核心的规则
波兰语不像英语只有单数/复数两种形态,它有四种复数形式,按数值选择不同的后缀:
| 后缀 | 适用数量 | 对应波兰语格 |
|---|---|---|
_one |
1 | 主格单数(nominative singular) |
_few |
2–4、22–24、32–34……(个位为 2–4) | 主格复数(nominative plural) |
_many |
5 及以上、11–21、25–31……(个位为 0、1 或 5–9) | 属格复数(genitive plural) |
_other |
小数与一般复数 | 通用形态 |
指南给出的标准示例是“连接(Connection)”一词:
英文源文件:
"connection_one": "Connection",
"connection_few": "Connections",
"connection_many": "Connections",
"connection_other": "Connections"
正确译法:
"connection_one": "Połączenie",
"connection_few": "Połączenia",
"connection_many": "Połączeń",
"connection_other": "Połączenia"
错误译法(格用错):
"connection_few": "Połączeń", // 2–4 不该用属格复数
"connection_many": "Połączenia" // 5+ 不该用主格复数
这条规则与 Airflow 工具链直接挂钩:ui_commands.py 中的 PLURAL_SUFFIXES 字典正是完整性检查的依据——"pl": ["_one", "_few", "_many", "_other"] 意味着检查器会要求每个复数词根都补齐这 4 个后缀键,缺任何一个都会计入 missing 统计。对照同一字典可以看到各语言的差异:阿拉伯语有 6 种形式(_zero 到 _other),日语/韩语/中文只有 _other,而波兰语恰是“四形式”语言之一(源码注释中也明确提到 “Polish has 4 forms”)。
在真实翻译文件中可以验证这一点。以 common.json 为例,其中每个可数量化的资源词都带齐四个后缀:
"dag_one": "Dag",
"dag_few": "Dagi",
"dag_many": "Dagów",
"dag_other": "Dagi",
"task_one": "Zadanie",
"task_few": "Zadania",
"task_many": "Zadań",
"task_other": "Zadania",
"taskInstance_one": "Instancja Zadania",
"taskInstance_few": "Instancje Zadań",
"taskInstance_many": "Instancji Zadań",
"taskInstance_other": "Instancje Zadań"
对比英文源 en/common.json 只有 dag_one / dag_other 两种形态,翻译时必须“展开”出 _few 与 _many——这正是 --add-missing 会依据 PLURAL_SUFFIXES 自动为缺失后缀生成 TODO: translate: 桩的原因。
复数形式与占位符联动
当字符串带有 {{count}} 插值时,四个后缀各承载一个完整的自然句。指南示例:
英文源:
"title": "Delete {{count}} connections"
正确译法(按形式拆成不同键):
"deleteConnection_one": "Usuń 1 połączenie",
"deleteConnection_few": "Usuń {{count}} połączenia",
"deleteConnection_many": "Usuń {{count}} połączeń"
错误译法——把变量名也翻译了:
"title": "Usuń {{liczba}} połączeń" // 变量名被翻译,插值将失效
这个规则与 SKILL.md 的全局规则一致:{{variable}} 是 i18next 的插值格式,变量名永远不能翻译或删除,允许为自然语序调整位置,但变量的大小写必须原样保留。仓库中的 pl/common.json 里可以看到该规则的大规模应用,例如:
"pendingDagRun_one": "{{count}} oczekujące wykonanie Daga",
"pendingDagRun_few": "{{count}} oczekujące wykonania Dagów",
"pendingDagRun_many": "{{count}} oczekujących wykonań Dagów",
"pendingDagRun_other": "{{count}} oczekujących wykonań Dagów"
四个形式里 Dagów/wykonań 等词尾随数量词 oczekujące(等待的)发生性数一致变化,这就是“逐形式翻译”而非机械拼接的体现。
3. 格变化:同一名词随语境变形
波兰语名词按语法格变形,翻译 UI 字符串时必须根据该词在句中的语法功能选择正确的格:
- 主格(Nominative)——作主语:
"title": "Wszystkie połączenia"(All connections); - 属格(Genitive)——表所属,“…的”:
"title": "Lista połączeń"(List of connections,połączeń为属格复数); - 宾格(Accusative)——作直接宾语:
"button": "Dodaj połączenie"(Add connection)。
这解释了为什么同一个词根在同一个 JSON 文件里会以不同词尾反复出现:作标题时是 połączenia(主格),作列表修饰语时是 połączeń(属格),作动词宾语时是 połączenie(宾格单数)。对评审者而言,判断一处波兰语翻译是否正确的关键就是“这个词在句子里承担什么成分,词尾是否与之匹配”。
4. 性别一致:名词、动词、形容词必须同性
名词的性别(阳/阴/中性)必须与配套的动词、形容词一致。指南示例:
正确(中性名词 usunięcie/Połączenie 语境 + 中性分词):
"message": "Połączenie zostało usunięte" // Connection was deleted
错误(误用阳性分词):
"message": "Połączenie został usunięty" // 中性名词 + 阳性动词/分词,错误
术语表还特别强调:“Deactivated”(Dag 头部状态)必须与其修饰的名词性别一致,如中性名词 zadanie(任务)对应 Deaktywowane,而阳性语境下为 Deaktywowany。仓库中的实际文件印证了这一点:pl/dag.json 中有 "deactivated": "Deaktywowany",而 pl/common.json 中描述上游资源被停用的提示写的是 Zasób nadrzędny został deaktywowany——两处名词性别不同,分词形式也随之不同。
5. 保留英文的术语与动词形式规范
pl.md 在“Unchanged Terms”一节列出必须保留英文(或按既定方式本地化)的词:
XCom—— Airflow 交叉通信机制名,不翻译(pl/common.json 中可见导航项译为"xcoms": "XComy",保留了XCom词干);ID—— 技术标识符,永远大写;Dag/Dags→ 使用Dag/Dagi(波兰语复数适配形式,注意单数始终是Dag而非DAG);- 日志级别:
CRITICAL、ERROR、WARNING、INFO、DEBUG保持原样。
SKILL.md 的全局术语表还包括 Airflow、Provider、REST API、JSON、PID、UTC、Schema 等;若 pl.md 与全局规则冲突,以 pl.md 为准。
动词形式与用户称呼方面:
- 命令式按钮统一用不定式/祈使式:
"Dodaj połączenie"(Add connection); - 状态提示用陈述式被动:
"Połączenie zostało usunięte"; - 询问用户时使用非正式第二人称 “ty”(小写),例如
"Czy chcesz kontynuować?",而不是过度正式的"Czy na pewno Pan chce kontynuować?"(带Pan的敬称版本被明确列为错误示范)。
快捷键值属于“字面键绑定”,除非本指南另有说明,一律不翻译(对应 SKILL.md 的 Hotkeys 规则)。pl/common.json 中 "hotkey": "d"、"hotkey": "e" 等键值均保持原样,只有外围的 tooltip 文案(Naciśnij {{hotkey}}, aby pobrać logi)被翻译。
6. 变音符号:9 个必须保留的特殊字符
波兰语使用一批带变音符号的字母,翻译文件中必须原样保留,写成无符号的 ASCII 拼写属于硬伤:
| 字母 | 正确 | 错误 |
|---|---|---|
| ą | będą | bedą |
| ć | połączenie | polaczenie |
| ę | usunięte | usuniete |
| ł | został | zostal |
| ń | koń | kon |
| ó | główna | glowna |
| ś | więcej | wiecej |
| ź | źródło | zrodlo |
| ż | żaden | zaden |
对照仓库中的 pl/common.json,大量词条依赖这些字符保持语义:Wypełnienia wsteczne(Backfills,含 ł)、żądanie grupowego usunięcia(批量删除请求,含 ż)、pomyślnie(successfully,含 ś)、Wsteczne 类词根等。翻译提交前把文件当作 UTF-8 文本检查变音符号是否丢失,是评审波兰语 PR 的基本动作。
7. 术语表:仓库实际使用的标准译法
pl.md 的“Terminology Glossary”给出三个容易译错的 Airflow 专属术语的首选译法:
| 英文 / 语境 | 首选波兰语 | 避免 |
|---|---|---|
| Consuming Asset(Dag run 消费的资源) | Zabierający zasób | |
| Bulk clear / delete / update(toaster 与按钮标签) | grupowy / grupowego / grupowej / grupowe … | |
| Deactivated(Dag 头部状态) | Deaktywowany / Deaktywowana / Deaktywowane |
两条补充说明:
- “bulk <动词>”一律用
grupowy并让词尾与名词保持格一致,例如żądanie grupowego wyczyszczenia(批量清除请求)、żądanie grupowej aktualizacji(批量更新请求),绝不用masowy; Deaktywowany必须与被修饰名词的性别一致(如中性zadanie→Deaktywowane)。
这些不是纸面规则,而是已经在代码库中落地的译法,可以直接在 pl/common.json 中检索验证:
"consumingAsset": "Zabierający zasób"—— 与首选译法逐字一致;toaster.bulkClear/bulkDelete/bulkUpdate系列全部采用grupowego/grupowej形态,如"Nie udało się wykonać żądania grupowego usunięcia {{resourceName}}"(Bulk Delete ... Request Failed);"Deaktywowany"出现在 pl/dag.json,deaktywowany小写形式出现在 pl/common.json 的资产停用提示中。
指南最后还有一条“Terminology Reference”的总原则:已有的 pl JSON 文件 就是权威术语表。翻译前先读现有文件,看该词在其他地方怎么译的,保持一致;只有当术语从未被翻译过时,才参照 en/ 英文源并按本指南规则新译。这与 i18n README 的政策一致:英文是唯一事实源,术语一致性优先,本地化指南文件在冲突时覆盖通用指南。
8. 验证:用 breeze 命令闭环
翻译完成后的验证流程(继承自 SKILL.md 的 Validation 一节):
# 完整性检查:输出表应为 0 missing、0 TODO、0 unused、100% 覆盖
breeze ui check-translation-completeness --language pl
# 缺键补桩 / 无用键清理
breeze ui check-translation-completeness --language pl --add-missing
breeze ui check-translation-completeness --language pl --remove-unused
# 最后跑 pre-commit 钩子,修复格式、许可证头与 lint 问题
prek run --from-ref main --hook-stage pre-commit
这套命令的判定逻辑可以从 ui_commands.py 的源码结构中看:check-translation-completeness 以英文命名空间文件为基准枚举必需键,对每个复数词根按 PLURAL_SUFFIXES["pl"] 的四个后缀展开出完整键集合,再与 locales/pl/ 下实际 JSON 求差集,得到 missing(缺键)与 unused(如多出的、波兰语不需要其词形变化的后缀键)两类清单;--add-missing 会把缺键按 TODO: translate: <英文原文> 桩的形式递归写入目标文件,--remove-unused 则反向删除。因此**“0 missing + 100% 覆盖”不仅是数字目标,而是工具对复数后缀展开规则执行结果的直接体现**——漏掉 taskInstance_many 这样一个键,检查表就会报 missing,PR 按 i18n README 的合入要求也无法通过完整性核验。
9. 小结
波兰语是 Airflow 支持的 20+ 个 UI 本地化中形态变化最复杂的语言之一。pl.md 用一组可执行的规则把这种复杂性收敛为翻译时的检查清单:
- 复数:
_one/_few/_many/_other四形式全覆盖,词尾随数量词正确变化; - 格与性:名词随句法成分变格,形容词/分词随名词性别一致;
- 术语:
XCom、ID、Dag(复数Dagi)、日志级别保留英文,bulk用grupowy系列,Deactivated用Deaktywowany系列并随性别变化; - 占位符:
{{count}}、{{hotkey}}等变量名永不翻译,只允许调整位置; - 变音符号:
ą ć ę ł ń ó ś ź ż必须保留; - 一致性:以 pl/ 目录中既有 JSON 为权威术语表,最终以
breeze ui check-translation-completeness --language pl全绿为准。
掌握这些规则后,无论是人工翻译还是借助 LLM 辅助翻译(i18n README 明确指出这类语言指南文件正是为 LLM 辅助翻译而设计的),产出的波兰语 UI 字符串都能在语法、术语和完整性三个层面通过仓库的工具链与评审要求。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00