在本文中,您将了解何时以及如何使用所有可用的 i18n 函数,以及编写字符串的最佳实践。

本文中的建议同时适用于您的 PHP 和 JavaScript 代码。您可以在 I18n functions 页面查看所有语言可用的函数。JavaScript 可用的函数也将被高亮显示。

基本字符串

最常用的函数是 __()。它返回其参数的翻译:

__( 'Blog Options', 'my-theme' );

另一个简单的函数是 _e(),它输出其参数的翻译。与其写成:

echo __( 'WordPress is the best!', 'my-theme' );

您可以使用更短的写法:

_e( 'WordPress is the best!', 'my-theme' );

__() 也适用于 JavaScript

变量

如果您在字符串中使用变量,如下面的示例所示,您需要使用占位符。

echo 'Your city is $city.'

请使用 printf 系列的函数。特别是 printf 和 sprintf 非常有用。例如:

printf(
    /* translators: %s: Name of a city */
    __( 'Your city is %s.', 'my-theme' ),
    $city
);

请注意,用于翻译的字符串是模板 "Your city is %s.",它在源代码和运行时都是相同的。

如果字符串中有多个占位符,建议使用 参数交换。在这种情况下,必须使用单引号 ('):双引号 (") 会告诉 PHP 将 $s 解释为 s 变量,这不是我们想要的。

printf(
    /* translators: 1: Name of a city 2: ZIP code */
    __( 'Your city is %1$s, and your zip code is %2$s.', 'my-theme' ),
    $city,
    $zipcode
);

在这里,邮政编码显示在城市名称之后。在某些语言中,以相反的顺序显示邮政编码和城市更为合适。使用 %s 前缀(如上例所示)允许这样做。翻译可以写成:

printf(
    /* translators: 1:ZIP code 2:Name of a city */
    __( 'Your zip code is %2$s, and your city is %1$s.', 'my-theme' ),
    $city,
    $zipcode
);

sprintf 也适用于 JavaScript 翻译:

const zipCodeMessage = sprintf(
    /* translators: 1:ZIP code 2:Name of a city */
    __( 'Your zip code is %2$s, and your city is %1$s.', 'my-theme'),
    city,
    zipcode
);

以下示例告诉您不应该做什么
这是错误的。

// This is incorrect do not use.
_e( "Your city is $city.", 'my-theme' );

用于翻译的字符串是从源代码中提取的,而不执行相关的 PHP。例如:变量 $city 可能是温哥华,所以当模板运行时,您的字符串将是 "Your city is Vancouver",但 gettext 无法提前知道 PHP 变量内部的内容。

由于在翻译字符串时变量的值未知,这将要求翻译人员知道变量 $country 的每一种情况。这并不理想,最好移除动态内容,让翻译人员专注于静态内容。

复数形式

基本复数化

如果您有一个随项目数量变化而变化的字符串。在英语中,您有 "One comment" 和 "Two comments"。在其他语言中,可能有多种复数形式。要在 WordPress 中处理这种情况,您可以使用 _n() 函数。

printf(
    _n(
        '%s comment',
        '%s comments',
        get_comments_number(),
        'my-theme'
    ),
    number_format_i18n( get_comments_number() )
);

_n() 接受 4 个参数:

  • singular – 字符串的单数形式(注意:在某些语言中,它可用于非一的数字,因此应使用 '%s item' 而不是 'One item')
  • plural – 字符串的复数形式
  • count – 对象的数量,它将决定是返回单数还是复数形式(有些语言有远超两种的形式)
  • text domain – 主题的文稿域

函数的返回值是对应于给定计数的正确翻译形式。

`_n() 也适用于 JavaScript

稍后处理复数化

您首先使用 _n_noop() 或 _nx_noop() 设置复数字符串。

$comments_plural = _n_noop(
    '%s comment.',
    '%s comments.'
);

在代码的稍后阶段,您可以使用 translate_nooped_plural() 来加载这些字符串。

printf(
    translate_nooped_plural(
        $comments_plural,
        get_comments_number(),
        'my-theme'
    ),
    number_format_i18n( get_comments_number() )
);

通过上下文消除歧义

有时一个术语在多个上下文中使用,即使英语中对每个上下文使用同一个词,也必须用其他语言分别翻译。例如,单词 Post 既可以用作动词 "Click here to post your comment",也可以用作名词 "Edit this Post"。在这种情况下,应使用 _x() 或 _ex() 函数。它与 __() 和 _e() 类似,但多了一个参数——上下文:

_x( 'Post', 'noun', 'my-theme' );
_x( 'post', 'verb', 'my-theme' );

在这两种情况下使用此方法,我们会得到原文的 Comment 字符串。但是,翻译人员将看到两个用于翻译的 Comment 字符串,每个都在不同的上下文中。

以 WordPress 德语版本为例:Post 是 Beiträge。德语中相应的动词形式是 beitragen。

请注意,与 __() 类似,_x() 也有一个 echo 版本:_ex()。前面的例子可以写成:

_ex( 'Post', 'noun', 'my-theme' );
_ex( 'post', 'verb', 'my-theme' );

使用您觉得能提高可读性和编码便利性的那个。

_x() and _nx()也适用于 JavaScript

描述

您可以在源代码中添加澄清注释,以便翻译人员知道如何翻译像 __( 'g:i:s a' ) 这样的字符串。它必须以单词 translators: 开头(全部小写),并且必须是 gettext 调用之前的最后一个 PHP 注释。这里有一个示例:

/* translators: draft saved date format, see http://php.net/date */
$saved_date_format = __( 'g:i:s a' );

多行示例:

/*
 * translators: Replace with a city related to your locale.
 * Test that it matches the expected location and has upcoming
 * events before including it. If no cities related to your
 * locale have events, then use a city related to your locale
 * that would be recognizable to most users.
 */
?>
<input placeholder="<?php esc_attr_e( 'Cincinnati' ); ?>" id="location" type="text" name="location" />

换行符

Gettext 不喜欢可翻译字符串中的 r(ASCII 码:13),所以请避免使用它,改用 n。

空字符串

空字符串保留用于 Gettext 的内部使用,您必须不要尝试国际化空字符串。这也毫无意义,因为翻译人员将没有上下文。

如果您有国际化空字符串的有效用例,请为两者添加上下文,以帮助翻译人员并符合 Gettext 系统的要求。

转义字符串

转义所有字符串是个好习惯,可以防止翻译人员运行恶意代码。有一些与国际化函数集成的转义函数。

<a title="<?php esc_attr_e( 'Skip to content', 'my-theme' ); ?>" class="screen-reader-text skip-link" href="#content" >
  <?php _e( 'Skip to content', 'my-theme' ); ?>
</a>
<label for="nav-menu">
  <?php esc_html_e( 'Select Menu:', 'my-theme' ); ?>
</label>

编写字符串的最佳实践

以下是编写字符串的最佳实践

  • 使用规范的英语风格——尽量减少俚语和缩写。
  • 使用完整的句子——在大多数语言中,词序与英语不同。
  • 按段落拆分——合并相关句子,但不要在单个字符串中包含整页文本。
  • 不要留下可翻译短语中的首尾空格。
  • 假设翻译后的字符串长度可能翻倍。
  • 避免使用特殊标记和控制字符——不要包含包围你文本的标签。
  • 不要在可翻译字符串中添加不必要的 HTML 标记。
  • 不要留下 URL 供翻译,除非它们可能有其他语言版本。
  • 将变量作为占位符添加到字符串中,因为在某些语言中占位符的位置会发生变化。
printf(
    __( 'Search results for: %s', 'my-theme' ),
    get_search_query()
);
  • 使用格式字符串代替字符串连接——翻译短语而不是单词——
printf(
    __( 'Your city is %1$s, and your zip code is %2$s.', 'my-theme' ),
    $city,
    $zipcode
);

总是优于

__( 'Your city is ', 'my-theme' ) . $city . __( ', and your zip code is ', 'my-theme' ) . $zipcode;
  • 尽量使用相同的单词和符号,以防止翻译多个相似的字符串(例如,不要执行以下操作)
__( 'Posts:', 'my-theme' ); and __( 'Posts', 'my-theme' );