☰
Weblate 中 Fluent 单语格式支持与质量检查配置完整指南
2026/10/10 5:24:31 网站建设 项目流程
  • 后端
  • 开发工具

【免费下载链接】weblate

Web based localization tool with tight version control integration.

项目地址:https://gitcode.com/gh_mirrors/we/weblate
点击查看免费下载

Fluent 是 Mozilla 主导的面向现代本地化的单语文本格式,它强调"非对称本地化"——一种语言中的简单字符串可以映射为另一种语言中的复杂多形态翻译。Weblate 自 4.8 版本起引入对 Fluent 的原生支持(fluent格式,文件扩展名.ftl),并在 5.0 版本中由 Henry Wilkes 贡献了一整套专门的语法与语义质量检查(参见 v5 变更日志)。本文以 Fluent 格式文档 为主体,结合 格式注册实现、Fluent 检查模块 与对应测试,完整说明 Fluent 在 Weblate 中的格式特性、组件配置方式、底层实现原理以及六项专属质量检查的启用与行为,帮助你直接在 Weblate 中落地 Fluent 本地化工作流。

Fluent 格式与"非对称本地化"

Fluent 是一种单语(monolingual)文本格式:每个翻译文件只包含一种语言的内容,字符串以key = value形式存在,键(key)与值(value)同处一个文件,而非像 gettext 那样把源语言和目标语言放在同一文件中。其核心设计是支持非对称本地化——源语言中的一个简单字符串,在目标语言中可能映射为一个包含多种形态、选择表达式(Select Expression)甚至多个属性的复杂翻译。这种不对称性对翻译管理系统提出了特殊要求:它不仅要保存"译文",还要保留 Fluent 特有的结构(值、属性、引用、选择分支),这正是 Weblate 对 Fluent 提供专属检查的原因。

在 Weblate 中,Fluent 由FluentFormat类注册实现,其关键元数据(见 ttkit.py):

属性值说明
format_idfluentAPI / 界面中使用的格式标识
nameFluent file组件配置中显示的名称
loader("fluent", "FluentFile")底层依赖 Translate Toolkit 的translate.storage.fluent.FluentFile解析器
autoload*.ftl自动识别.ftl扩展名
language_formatbcp语言代码使用 BCP 47 规范(如cs-CZ)
mimetypetext/x-fluent导出/下载时的 MIME 类型
extensionftl标准文件扩展名
empty_file_template""新翻译文件以空模板创建
monolingualTrue单语格式,需要单独指定基础语言文件
supports_descriptionsTrue支持为字符串添加说明(description)

格式特性总览

根据自动生成的格式特性片段 fluent-features.rst,Weblate 对 Fluent 的支持能力如下:

特性支持情况
文件扩展名.ftl
语言类型单语(Monolingual)
复数支持否(Fluent 通过选择表达式实现复数,不使用 Weblate 的复数机制)
描述(Descriptions)支持
说明(Explanation)不支持
上下文(Context)不支持(键即上下文)
位置(Location)不支持
标志(Flags)不支持
API 标识fluent
只读字符串不支持
移除过时字符串不支持
由该格式附加的检查标志fluent-source-syntax、fluent-target-syntax、fluent-parts、fluent-references、fluent-source-inner-html、fluent-target-inner-html、ignore-xml-tags、ignore-xml-invalid

其中最后两项目ignore-xml-tags与ignore-xml-invalid是自动附加的——由于 Fluent 消息的值常被直接当作 HTML 的innerHTML使用,通用 XML 检查会产生大量误报,因此由 Fluent 专属的fluent-*-inner-html检查取代,同时显式忽略 XML 类检查(参见 FluentFormat.check_flags 定义)。

在 Weblate 中配置 Fluent 组件

在创建或编辑组件时,按以下配置即可启用 Fluent 翻译(表格源自 Fluent 格式文档):

组件字段推荐值
文件掩码(File mask)locales/*/messages.ftl
单语基础语言文件(Monolingual base language file)locales/en/messages.ftl
新翻译模板(Template for new translations)空(Empty)
文件格式(File format)Fluent file

要点说明:

  • 文件掩码:使用通配符覆盖各语言目录,例如locales/*/messages.ftl会匹配locales/cs/messages.ftl、locales/de/messages.ftl等。对应的测试断言EXPECTED_PATH = "locales/cs-CZ/messages.ftl"(见 FluentFormatTest),印证语言目录使用 BCP 47 语言代码。
  • 基础语言文件:Fluent 是单语格式,必须指定基础语言文件(通常为英文),Weblate 以其中的键集合作为翻译源。
  • 新翻译模板为空:新建语言时直接创建空文件,而非复制基础语言文件。
  • 语言代码:language_format = "bcp"意味着语言目录名采用 BCP 47 规范。

示例文件解析

文档引用的示例文件 weblate/trans/tests/data/cs.ftl 展示了 Fluent 消息的基本形态:

hello = Ahoj "světe"!\n orangutan = Orangutan má %d banán.\n try = Zkus Weblate na <https://demo.weblate.org/>!\n thanks = Děkujeme za použití Weblate.

可观察到的要点:

  • 每个条目以键开头(如hello),等号右侧是值;
  • 值内可以包含转义序列\n、引号、格式化占位符%d、HTML 内容等,这些都属于合法的 Fluent 文本;
  • 该文件共 4 条消息,测试断言COUNT = 4、FIND_CONTEXT = "hello"且查找值Ahoj "světe"!\\n(见 FluentFormatTest)。

此外,FLuentFormatTest中NEW_UNIT_MATCH = b"\nkey = Source string"验证了新增单元(翻译条目)时的序列化输出格式为key = Source string。

底层实现:格式加载与写入

Weblate 对 Fluent 的支持建立在 Translate Toolkit 的FluentFile之上,由FluentFormat(继承TTKitFormat)桥接。核心实现细节:

写入时的语法自校验

FluentUnit.set_target()(见 ttkit.py)在写入译文时做了额外的安全处理:

  1. 先保存旧的目标与源值;
  2. 写入新目标值;
  3. 调用self.unit.to_entry()触发序列化,从而提前发现任何 Fluent 语法问题;
  4. 一旦序列化抛出异常,立即回滚旧内容并重新抛出异常。

也就是说,翻译者在 Weblate 界面中保存不合法的 Fluent 语法时,写入会被拒绝并回滚,而不是把损坏的语法写入仓库。底层抛出的FluentContentError在 translation.py 中被识别并作为"已处理异常"记录(仅记录日志,不当作崩溃级错误上报),对应测试见 test_models.py 中 test_commit_retry_unit_fluent_content_error_uses_handled_logging。

键编辑支持与限制

从 source_edit.py 看,fluent被列入KEY_FORMATS(键格式集合),意味着在单语模式下允许就地编辑键(context/source)。但 edit_identity() 明确限制:带属性(attributes)或选择器(selectors)的 Fluent 消息不允许编辑,否则抛出ValidationError("Editing Fluent messages with attributes or selectors is not supported.")。这与 Fluent 复杂消息的内部结构有关——这类消息一旦改变键,其嵌套结构难以安全重构。对应测试见 test_source_edit.py 的 test_complex_fluent_edit_rejected。

fluent-type 标志

FluentUnit.flags(ttkit.py)会为每个单元附加fluent-type标志,取值为Message或Term。fluent-type在 flags.py 中注册为带类型的标志(TYPED_FLAGS),用于下游检查区分消息与术语。测试断言默认导出标志为fluent-type:Message(见 FluentFormatTest)。

Fluent 专属质量检查(默认关闭,需手动启用)

Weblate 5.0 起为 Fluent 提供 6 项专属检查,全部默认禁用(default_disabled = True),需在组件的质量检查设置中手动启用。它们注册于 checks/defaults.py,实现在 weblate/checks/fluent/ 目录下,完整测试见 test_fluent_checks.py(约 2900 行,覆盖 6 项检查)。

1. Fluent 源语法检查(fluent-source-syntax)

实现在 syntax.py,属于源字符串检查。它使用FluentUnitConverter将源字符串构造成 Fluent 单元并解析,若出现语法错误则报错,错误信息形如Fluent syntax error: {error}.。测试用例显示大量合法语法不会误报,包括:普通文本、emoji、test [string]、] test string、test = string、含未闭合 HTML 标签的文本(test <p string)、引用({ message }、{ $variable })、函数调用({ FUNCTION($n, val1: "hello") })、字面量({ "[" }、{ 3 })、转义字符与 Unicode 转义(\u27BD、\U01F700)、选择表达式({ $var -> *[other] ok })等(见 test_syntax_ok)。

2. Fluent 译文语法检查(fluent-target-syntax)

实现在 syntax.py,属于译文检查,行为与源语法检查一致,只是作用在译文上。

3. Fluent 部件检查(fluent-parts)

实现在 parts.py。Fluent 消息由多个"部件"组成:一个可选值(value,消息正文)与若干属性(attributes)。例如:

# 值 + 两个属性 This is the Message value .title = This is the title attribute .alt = This is the alt attribute

该检查确保译文与源在部件上一一对应:源消息有值则译文必须有值,源没有值则译文也不可有;源用到的属性译文必须全部出现,且不得添加额外属性。该检查不应用于 Term(术语)——术语永远有值,且术语的属性通常与语言相关(如语法规则),不必在每个翻译中出现。

4. Fluent 引用检查(fluent-references)

实现在 references.py。Fluent 消息可以引用其他消息、术语、属性或变量,例如:

Here is a { message }, a { message.attribute } a { -term } and a { $variable }. Within a function { NUMBER($num, minimumFractionDigits: 2) }

该检查要求译文使用与源相同集合、相同次数的引用,不允许新增或遗漏;对消息,还会逐一比对每个属性内部的引用。针对选择表达式有专门规则:

  • 源中的每个变体(variant)必须在译文中找到引用集合相同的对应变体;
  • 若变量引用同时出现在选择器的选择器与某个变体内部,则其他变体也被视为隐含包含该引用(如{ $num -> [one] an apple *[other] { $num } apples }中的[one]变体被视为也引用$num);
  • 仅出现在选择器中的引用(通常是术语属性,如-term.starts-with-vowel)不计入必需引用,因为它们不构成最终可见文本,且选择表达式的存在本身是语言相关的。

5/6. Fluent 源/译文 innerHTML 检查(fluent-source-inner-html / fluent-target-inner-html)

实现在 inner_html.py。Fluent 的值常被直接用作 HTML 元素的innerHTML(例如 Fluent DOM 包的使用方式)。该检查模拟 HTML5 合规解析器对值进行解析,专门捕捉会导致字符串"意外丢失"的情况——例如误打开未闭合的标签、插入字符引用,同时验证有意书写 HTML 时的良好实践(闭合标签匹配、字符引用合法、属性值加引号)。

注意:该检查仅作用于消息或术语的值(value),不作用于属性——属性在 Fluent 中往往是 HTML 属性值(可包含任意字符串),术语属性则多为语言特性,仅在选择器中使用(见 inner_html.py 的类文档)。

以上检查共享同一套基础设施FluentUnitConverter(utils.py):它依据fluent-type标志判断是 Message 还是 Term(标志缺失时按键是否以-开头猜测,Fluent 术语的键约定以-开头),将翻译单元转换为FluentUnit后进行解析,并提供语法错误与部件、引用提取能力。

与其他格式的差异与注意事项

  • 复数处理:Fluent 格式本身不支持 Weblate 的复数机制,复数逻辑在 Fluent 内通过选择表达式完成,因此supports_plural = False。
  • 单语配置:与 JSON、YAML 等单语格式一样,Fluent 组件必须配置"单语基础语言文件",否则无法确定需要翻译的键集合。
  • 键识别变更:v4 变更日志提示 Fluent 格式曾调整部分字符串的识别方式,升级后可能需要重新核对字符串状态(见 docs/changes/v4.rst);而 5.0 带来的语法检查改进则在 v5 变更日志 中有记录。
  • 启用检查:6 项 Fluent 专属检查默认关闭,建议在启用 Fluent 组件后于项目/组件"质量检查"页面打开fluent-source-syntax、fluent-target-syntax与fluent-parts,以保证仓库内语法与结构的一致性;fluent-*-inner-html仅在消息值确会被当作 HTML 渲染时启用,避免对纯文本项目产生不必要干扰。

小结

Fluent 的单语、非对称特性决定了它不能按传统双语格式处理。Weblate 通过FluentFormat桥接 Translate Toolkit 完成解析与序列化,在写入时自校验语法防止损坏文件入库,并配套 6 项针对 Fluent 语义的专属质量检查(语法、部件、引用、innerHTML),覆盖了 Fluent 本地化中最容易出错的环节。按照本文给出的locales/*/messages.ftl+ 基础语言文件配置,即可在 Weblate 中构建一套语法安全、结构可控的 Fluent 翻译流水线;如需进一步了解 Fluent 语法本身,可参阅 docs/formats/fluent.rst 中指向的 Project Fluent 官方文档链接。

  • 后端
  • 开发工具

【免费下载链接】weblate

Web based localization tool with tight version control integration.

项目地址:https://gitcode.com/gh_mirrors/we/weblate
点击查看免费下载
上一篇:WAMR原生API导出终极指南:3步实现C/C++函数与WASM模块的无缝交互
下一篇:Blender MCP 插件手把手教程:怎么装、怎么配、连不上怎么查

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询