恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Weblate 翻译管理实战:新增字符串、语言文件、字符串变体与标签全解析
首页
资讯中心
/
Weblate 翻译管理实战:新增字符串、语言文件、字符串变体与标签全解析
Weblate 翻译管理实战:新增字符串、语言文件、字符串变体与标签全解析
发布时间:2026/10/11 11:52:43
后端开发工具【免费下载链接】weblateWeb based localization tool with tight version control integration.项目地址https://gitcode.com/gh_mirrors/we/weblate点击查看免费下载本篇技术指南聚焦 Weblate 开源本地化平台Web based localization tool with tight version control integration的翻译管理工作流系统讲解如何向组件添加新字符串、新增/删除翻译语言、利用字符串变体Variants分组翻译以及用标签Labels分类管理词条。读者阅读完本篇后将掌握组件配置项如new_base、new_lang、language_code_style、variant_regex的完整语义与取值范围并能结合源码理解 Weblate 底层如何生成语言文件、计算变体分组与维护标签数据。本文以 docs/devel/translations.rst 为骨架辅以 Component 模型、Variant 模型、Label 模型 及对应测试进行纵深印证。一、添加新字符串从基础文件到 Weblate 内部管理1.1 新字符串的来源组件基础文件new_base在 Weblate 中新字符串默认不会凭空产生而是来源于组件的基础文件base file。当字符串出现在基础文件中它们即可被翻译该基础文件的路径由组件配置项new_base指定其字段定义位于 component.pynew_base models.CharField( verbose_namegettext_lazy(Template for new translations), max_lengthFILENAME_LENGTH, blankTrue, help_textgettext_lazy( Filename of file used for creating new translations. For gettext choose .pot file. ), validators[validate_filename], )几个关键点对于gettext 格式.po建议选择.pot模板文件作为new_base因为 pot 只含源字符串是天然的“待翻译清单”对于大多数单语monolingual翻译流例如 Android 资源、JSON 等格式通常不需要独立的基础文件可以从空文件开始新字符串由开发者写入源文件后同步进 WeblateblankTrue表示该字段可留空此时 Weblate 是否能够创建新翻译文件取决于文件格式是否支持“空文件起步”。1.2 在 Weblate 内直接添加字符串对于大多数文件格式Weblate 支持直接在现有文件中添加新字符串前提是组件启用了对应能力见后文manage_units。添加时可以设置以下选项Context上下文适用于双语bilingual格式用来区分在不同上下文中出现的相同字符串。例如 gettext 中同一个英文文本出现在不同 msgctxt 下就靠 Context 区分Auto-adjust context when an identical string already exists当已存在相同字符串时自动调整上下文开启后若目标字符串已存在于翻译中Weblate 会自动为 Context 追加数字后缀避免冲突。例如已存在Context自动生成Context (1)、Context (2)。关于 Context 在各文件格式中的具体语义可进一步参阅 文件格式文档 中针对各格式的说明如 gettext 格式、xliff 格式。1.3 底层支撑manage_units 与内部单元管理“在 Weblate 内直接增删字符串”依赖组件的manage_units开关其定义同样位于 component.pymanage_units models.BooleanField( verbose_namegettext_lazy(Manage strings), defaultFalse, help_textgettext_lazy( Enables adding, removing, and editing source strings and keys in Weblate. If your strings are extracted from the source code or managed externally you ... ), )从源码结构看该开关默认关闭defaultFalse因为多数项目的源字符串由代码仓库统一管理只有当团队希望把字符串维护工作也搬进 Weblate 时例如纯运营团队维护文案才应开启。开关开启后翻译界面中的“工具Tools”菜单才会提供增删字符串的入口这与后文“手动添加变体”“移除字符串”等能力是配套的。二、添加新翻译语言文件的生命周期2.1 请求模式new_lang 的五种行为当用户请求为组件添加一种新语言时Weblate 的行为由组件配置new_lang控制。该字段在 component.py 中定义可选值及其文案定义在 inherited_settings.py取值行为说明contact联系维护者需要人工介入处理url指向翻译说明 URL引导用户查看项目说明文档add直接创建新的语言文件默认值existing仅创建项目已有语言新语言需联系维护者none禁用添加新翻译其中none与url属于“禁用模式”inherited_settings.py 中还定义了DISABLED_NEW_LANGUAGE_MODES (none, url)以及复杂的继承过滤逻辑用于在项目/分类/组件三层继承结构中正确识别哪些组件不允许新增语言。同时new_lang与language_code_style等配置一样支持继承inherit_new_lang字段默认True即组件可继承其所属分类或项目的设置覆盖后即断开继承详见 INHERITABLE_COMPONENT_SETTINGS。2.2 新语言文件如何生成格式差异与 new_base 的作用不同的文件格式对“新语言文件”的初始化方式差异很大文档中列举了典型场景只包含已翻译字符串部分格式期望新语言文件为空文件、仅收录翻译过的字符串例如Android 资源见 android.rst包含全部键另一些格式期望所有键keys都存在于每个语言文件中例如gettext见 gettext.rst复制源文档并标记待编辑基于文档的格式例如ODF 电子表格/文档见 odf.rst会以源文档的副本作为起点其中所有字符串被标记为“需要编辑”取决于处理框架某些情况下行为并不取决于格式本身而是取决于你处理翻译的框架约定例如JSON见 json.rst在不同生态中两种做法都存在。配置new_base后Weblate 会以该文件为模板启动新翻译——注意启动时会从该文件中移除所有已有的翻译内容它只用作模板不保留译文。若new_base为空且文件格式支持则创建空文件新字符串在翻译完成后按需追加写入。源码层面Component.add_new_language()component.py完整实现了上述流程其关键调用链为can_add_new_language()检查当前用户与语言是否被允许component.pyformat_new_language_code(language)计算生成的文件语言代码component.py通过language_regex正则校验语言代码合法性超时会记录Component language filter timed out错误调用file_format_cls.get_language_filename(self.filemask, code)解析目标文件名然后file_format.add_language(fullname, language, base_filename, ...)在仓库锁内创建文件发出translation_post_add信号并执行translation.git_commit(...)提交最终触发对新增文件的解析。2.3 语言代码样式与语言别名新语言文件的文件名由组件配置language_code_style决定该字段定义于 component.py可选值多达 14 种inherited_settings.py取值样式说明空默认基于文件格式posixPOSIX 风格下划线分隔posix_lowercasePOSIX 风格下划线分隔小写bcpBCP 风格连字符分隔posix_longPOSIX 风格含国家代码posix_long_lowercasePOSIX 风格含国家代码小写bcp_longBCP 风格含国家代码bcp_legacyBCP 风格旧语言代码bcp_lowerBCP 风格连字符分隔小写androidAndroid 风格appstoreApple App Store 元数据风格googleplayGoogle Play 元数据风格linuxLinux 风格linux_lowercaseLinux 风格小写此外项目级配置language_aliases语言别名会被反向应用即如果别名把zh-Hant映射到zh_Hant那么生成文件名时会把计算出的zh_Hant反解回zh-Hant。这一逻辑在format_new_language_code()中可见def format_new_language_code(self, language): code self.file_format_cls.get_language_code( language.code, self.effective_language_code_style ) # Apply language aliases language_aliases {v: k for k, v in self.project.language_aliases_dict.items()} if code in language_aliases: code language_aliases[code] return code反向别名映射正是为了让生成的仓库文件名符合团队约定例如仓库历史上一直使用 BCP 风格的pt-BR而非 POSIX 的pt_BR。语言代码的解析规则可进一步参考 语言代码解析 与 语言代码风格配置。2.4 通过远程仓库添加语言文件如果在连接的远程仓库中直接新增了语言文件那么当 Weblate 更新本地仓库触发sync_git_repo/update_branch流程时对应翻译会自动被加入组件——无需在 Weblate 界面重复操作。仓库更新行为由 VCS 更新配置控制详见 VCS 相关文档 与 连续翻译/自动更新。三、移除现有翻译3.1 删除语言、组件或项目语言Language、组件Component或其所属项目Project都可以从 Weblate 中删除操作入口统一在对应对象的菜单Operations操作→ Removal移除。发起移除后界面会列出将被删除的组件清单并要求输入对象的slug进行确认——slug即该对象的路径名可从其 URL 中直接看到。确认后删除生效若组件关联了远程仓库相关文件也会随之从仓库移除。3.2 删除部分字符串的两种方式如果只想删除个别字符串而非整个语言/组件文档给出两条路径在源文件中手动删除直接在仓库的源文件中移除该字符串Weblate 在后续仓库更新时会将对应词条从翻译项目中同步移除在 Weblate 界面删除4.5 版本新增编辑字符串时通过Operations操作→ Remove移除按钮删除。该能力在不同文件格式下的表现有差异具体取决于组件的manage_units配置component.py因为“在 Weblate 内删除词条”本质上与“管理字符串”是同一能力体系。与 2.4 对称若在远程仓库中删除语言文件Weblate 更新本地仓库后相应翻译也会从组件中移除。从源码看字符串删除最终会落在 Translation 的删除方法如translation.delete_unit见 test_variants.py 中通过translation.delete_unit(None, unit)删除单元后变体计数归零的测试删除后 Weblate 会清理关联的变体、标签与统计缓存。四、字符串变体Variants把相关词条聚成一簇4.1 变体的价值变体Variants用于把若干相似/相关的字符串聚合在一起让译者在同一个地方看到某一词条的所有变体从而保证译法一致性。典型的例子是缩写abbreviationmonthShort月份缩写与month完整月份在翻译时应保持同一套术语体系。4.2 自动变体基于键的正则表达式对于单语翻译可在组件配置中设置variant_regex正则表达式Weblate 会自动按翻译键Key分组生成变体。该字段定义在 component.pyvariant_regex RegexField( verbose_namegettext_lazy(Variants regular expression), validators[validate_re_nonempty], max_length190, default, blankTrue, help_textgettext_lazy( Regular expression used to determine variants of a string. ), )工作机制当某个翻译键匹配该正则时匹配部分会被移除得到根键root key所有拥有相同根键的字符串包括键恰好等于根键的那条构成一个变体组。在组件配置中定义变体正则表达式Weblate 据此自动为单语翻译分组。文档给出了两个典型示例使用场景正则表达式被匹配的翻译键后缀识别(Short|Min)$monthShort、monthMin、month内联识别#[SML]dial#S.key、dial#M.key、dial.key后缀识别示例正则(Short|Min)$匹配monthShort与monthMin移除匹配部分后根键都是month而month本身也恰好等于根键于是三者归入同一变体组。内联识别示例#[SML]匹配dial#S.key、dial#M.key中的#S/#M根键为dial.key三条键聚为一组。测试 test_variants.py 验证了该行为为组件设置variant_regex (Min|Short|Max)$并添加bar、barMin、barShort三个单元后Variant.objects.count() 1且该变体组的unit_set.count() 6单语组件中每个键同时存在于源语言与目标语言故 3 键 × 2 语言 6 个单元清除正则后变体记录归零。内联场景测试则验证了//(SCRTEXT_S|SCRTEXT_M|...)这类键中部匹配的正则同样生效。4.3 手动变体variant:SOURCE 标志自动正则依赖“键”的存在因此双语格式bilingual或键名互不匹配的字符串无法自动分组。为此Weblate 4.5 起支持手动变体为字符串设置variant:SOURCE标志即可把它与SOURCE这条字符串链接为变体。用法在字符串的额外标志extra flags中写入variant:Default string注意 SOURCE 需加引号内容为源字符串文本适用场景双语翻译中键不存在的场合或键不同但翻译时应当一起考虑的字符串硬性限制变体源字符串最长 768 字符超出无法作为变体源快捷入口当组件开启manage_units时翻译过程中可通过Tools工具菜单为字符串追加额外变体清理机制移除标志后变体自动解散若某变体组中最后一个定义单元被删除变体记录随之删除见 test_variants.py 的删除测试。4.4 变体的底层模型与同步逻辑变体在数据库中由独立模型Variant承载variant.pyclass Variant(models.Model): component models.ForeignKey(trans.Component, ...) variant_regex RegexField(max_lengthVARIANT_REGEX_LENGTH, blankTrue) key models.TextField() defining_units models.ManyToManyField(trans.Unit, related_namedefined_variants)一个Variant记录同时绑定component与variant_regex自动变体或空正则手动变体key即根键或variant:SOURCE中的源字符串defining_units多对多关联“定义单元”数据库层用MD5(key) component variant_regex构造唯一约束兼顾长键索引效率与唯一性模型强制要求 PostgreSQL 后端required_db_vendor postgresql。单元侧的逻辑在 unit.py 的update_variants()中单元保存/变更时若标志含variant则创建/更新手动变体链接若组件配置了variant_regex则用regex_findall对self.context单语翻译的键做匹配正则执行设有时长保护超时会记录Component variant regex timed out警告并跳过匹配避免恶意正则拖垮性能。翻译时属于同一变体组的字符串集中展示译者可在同一位置对照翻译所有变体。4.5 相关主题延伸变体与检查项的联动可参考 用户端检查项文档术语表Glossary中的变体处理可参考 术语表文档。五、字符串标签Labels按文本与颜色分类管理5.1 标签的作用与创建标签Labels用于在项目配置层面把组件内的翻译字符串按文本描述 颜色划分成不同类别从而在大规模项目中快速定位某类词条例如“UI 文案”“法律条款”“占位符说明”等。标签属于项目级概念标签挂在 Project 上可被该项目下所有组件复用。在项目配置中创建带颜色标识的标签用于分类组件内的翻译字符串。源码层面的Label模型位于 label.pyclass Label(models.Model): color models.CharField(...) # 颜色取自 ColorChoices ...每个标签包含名称name、**描述description与颜色color**三要素LabelQuerySet提供按名称排序等查询能力测试 test_labels.py 验证了列表按名称字典序Alpha → Middle → Zulu展示同项目内标签名唯一重复创建会被拒绝提示Label with this Project and Label name already exists.见 test_labels.py。5.2 标签如何绑定到字符串标签与字符串Unit之间是多对多关系字段定义于 unit.pylabels ManyToManyField(Label, verbose_namegettext_lazy(Labels), blankTrue)为字符串打标签的常规途径批量编辑bulk editing在字符串列表页使用“附加additional”功能批量给筛选出的字符串添加标签对应labels字段批量赋值批量操作插件使用weblate.flags.bulk插件见 addons.rst通过标志规则批量设置标签。标签在单元上还以**标志flag**形式存在Label.get_label_flag()返回label:{name}形式的标志见 label.py这意味着标签可与 Weblate 的标志体系互通例如通过weblate.flags.bulk插件按标志批量赋值标签。5.3 标签删除与统计维护从测试 test_labels.py 可见删除仍被字符串引用的标签是允许的级联清理单元上的关联并且 Weblate 会刷新受影响的统计缓存test_delete_assigned_refreshes_totals对源字符串的修改也会触发标签统计的增量更新test_source_change_recalculates_cached_label_stats说明标签统计走的是带版本号generation的缓存机制避免并发下统计错乱。六、实战要点速查新增字符串优先在源仓库基础文件中添加需在 Weblate 内直接添加时开启组件manage_units并善用 Context 与“自动调整 Context”避免双语格式的键冲突新增语言按团队流程选择new_langadd/existing/contact/url/none设置new_base决定新语言文件的初始内容形态用language_code_style控制文件名风格必要时在项目层配置language_aliases以反向映射出符合仓库历史的语言代码删除语言/组件/项目级删除需输入slug确认删除个别字符串优先在源文件操作仓库同步后生效也可在开启manage_units的组件中用编辑界面的 Remove 按钮变体单语翻译用variant_regex自动分组匹配部分即根键差异双语或无键场景用手动variant:SOURCE标志源字符串 ≤ 768 字符二者最终都汇聚到Variant模型翻译界面统一分组展示标签项目级创建名称/描述/颜色通过批量编辑或weblate.flags.bulk插件按label:标志批量赋值删除时系统自动维护统计缓存。所有配置字段new_base、new_lang、language_code_style、variant_regex、manage_units的完整校验逻辑均可在 weblate/trans/models/component.py 中查阅选项定义集中在 weblate/trans/inherited_settings.py行为验证可复现于 test_variants.py 与 test_labels.py。赞分享后端开发工具【免费下载链接】weblateWeb based localization tool with tight version control integration.项目地址https://gitcode.com/gh_mirrors/we/weblate点击查看免费下载相关推荐Thunderbird for Android 字符串与语言管理实践指南从源字符串到 Weblate 全流程Thunderbird for Android 字符串与语言管理实践指南从源字符串到 Weblate 全流程 Thunderbird for Android移动开发企业应用Weblate PHP 字符串翻译格式PHP strings详解单语翻译、组件配置与源码实现Weblate PHP 字符串翻译格式PHP strings详解单语翻译、组件配置与源码实现 PHP 项目的本地化文件通常以 lang/ /texts.p后端开发工具Stl.Fusion核心概念解析揭秘DREAM架构的魔力Stl.Fusion核心概念解析揭秘DREAM架构的魔力 Stl.Fusion是一个革命性的开源框架它通过DREAM分布式反应式记忆化架构让开发者能够轻创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考