OpenStack 使用指南

OpenStack I18N 团队翻译消息的能力有限,因此我们希望尽可能提高他们的工作效率,通过识别他们需要翻译的最有用的文本来实现。所有用户通过异常或 API 调用看到的文本消息都应标记为可翻译。但是,某些异常仅用于在模块之间发出错误信号,不打算呈现给用户。这些不需要翻译。正如下面解释的那样,日志消息也不需要翻译。

Gettext 上下文形式和复数形式

在不同的上下文中,有时应该使用 TranslatorFactory.contextual_form 将相同的单词翻译成不同的短语。

并建议使用以下代码来使用上下文形式

# The contextual translation function using the name "_C"
_C = _translators.contextual_form

...
msg = _C('context', 'string')

在某些语言中,有时翻译后的字符串会根据不同的项目数量使用 TranslatorFactory.plural_form 而不同

并建议使用以下代码来使用复数形式

# The plural translation function using the name "_P"
_P = _translators.plural_form

...
msg = _P('single', 'plural', count)

上下文形式和复数形式仅在需要时使用。默认情况下,翻译应使用 _()

注意

这两个函数仅在 oslo.i18n >= 2.1.0 中可用。

日志翻译

注意

从 Pike 系列开始,OpenStack 不再支持日志翻译。无需在新代码中添加翻译说明,并且可以从旧代码中删除说明。保留以下文档是为了帮助开发人员了解现有用法以及如何删除它。

支持被取消主要是基于操作员的反馈,他们认为这些不仅不需要,而且也不受欢迎,因为它们分散了提供有关任何特定日志消息的有用信息的网页集合,从而降低了通过搜索消息在网络上找到这些网页的机会。有关更多详细信息,请参阅电子邮件线程理解日志域更改,该线程位于 openstack-dev 邮件列表中。

OpenStack 以前支持使用单独的消息目录翻译一些日志级别,因此具有单独的标记函数。这些众所周知的名称由构建系统作业使用,这些作业从源代码中提取消息并将其传递给翻译工具。

级别

Function

INFO

_LI()

WARNING

_LW()

ERROR

_LE()

CRITICAL

_LC()

注意

调试级别的日志消息从不翻译。

使用标记函数

标记函数用于标记代码中的可翻译字符串。字符串使用执行源代码检查以查找这些特定标记的工具提取到目录中,因此函数参数必须只是一个字符串。

例如:不要这样做

# WRONG
msg = _(variable_containing_msg)

而是使用这种风格

# RIGHT
msg = _('My message.')

选择标记函数

不同标记函数的作用是将可翻译的消息分成不同的目录,翻译团队可以优先翻译这些目录。选择正确的标记函数很重要,以确保用户看到的消息将被翻译,并帮助翻译团队管理他们的工作量。

所有使用 _() 标记的内容都将被翻译。优先处理从使用日志标记函数标记的字符串创建的目录由各个翻译团队及其用户决定,但预计他们将在警告或信息之前处理关键和错误消息。

_() 适用于任何面向用户的消息,即使它也将发送到日志文件。这确保了翻译后的消息可供用户使用。

日志标记函数(_LI()_LW()_LE()_LC())不应再使用,并且应删除现有的用法。每当消息传递到当前上下文之外(例如作为异常的一部分)时,必须使用 _() 标记函数。

一种常见的模式是定义单个消息对象并多次使用它,用于日志调用和异常。在这种情况下,必须使用 _(),因为消息将出现在可能呈现给用户的异常中。

但是,现在日志消息不再翻译,不幸的是,有必要使用两个单独的字符串:一个用于日志消息的普通字符串,一个用于异常的可翻译字符串。

例如,不要这样做

# WRONG
msg = _('There was an error.')
LOG.error(msg)
raise LocalExceptionClass(msg)

或这样

# EVEN MORE WRONG
msg = _LE('There was an error.')
LOG.error(msg)
raise LocalExceptionClass(msg)

而是使用这种风格

# RIGHT
LOG.error('There was an error.')
raise LocalExceptionClass(_('An error occurred.'))

将变量添加到翻译后的消息

翻译后的消息不应与其他文字字符串组合以创建部分翻译的消息。例如,不要这样做

# WRONG
raise ValueError(_('some message') + ': variable=%s' % variable)

而是使用这种风格

# RIGHT
raise ValueError(_('some message: variable=%s') % variable)

将变量引用包含在翻译后的消息中,允许翻译人员考虑语法规则、从左到右与从右到左渲染的差异以及其他因素,以使翻译后的消息对最终用户更有用。

任何包含多个变量的消息都应使用命名插值而不是位置插值,以便翻译人员可以移动字符串中的变量,以考虑语法和书写方向的差异。

例如,不要这样做

# WRONG
raise ValueError(_('some message: v1=%s v2=%s') % (v1, v2))

而是使用这种风格

# RIGHT
raise ValueError(_('some message: v1=%(v1)s v2=%(v2)s') % {'v1': v1, 'v2': v2})