【问题标题】:gettext, how to handle homonyms?gettext,如何处理同音异义词?
【发布时间】:2013-04-28 07:49:29
【问题描述】:

使用 gettext

单值

echo gettext( "Hello, world!\n" );

复数

printf(ngettext("%d comment", "%d comments", $n), $n);

英文同音字?

echo gettext("Letter");// as in mail, for Russian outputs "письмо"
echo gettext("Letter");// as in character, for Russian outputs "буква" 

与英文单词“character”一样,可以是人的字符,也可以是字母! gettext 应该如何识别同音异义词的正确翻译?

【问题讨论】:

标签: php gettext


【解决方案1】:

您正在寻找的是 gettext 的上下文,它可以解决像您的示例这样的歧义。您可以在documentation 中找到有关信息。所需的方法 pgettext 仍然没有在 PHP 中实现,因此您可以使用 php 文档中 user comment 中所述的辅助方法。

if (!function_exists('pgettext')) {

  function pgettext($context, $msgid)
  {
     $contextString = "{$context}\004{$msgid}";
     $translation = dcgettext('messages', contextString,LC_MESSAGES);
     if ($translation == $contextString)  return $msgid;
     else  return $translation;
  }

}

在你的情况下是

echo pgettext('mail', 'Letter');
echo pgettext('character', 'Letter');

【讨论】:

  • 最好使用textdomain(NULL) 而不是'messages',这样该函数的行为方式与C 宏等效项相同。
  • 另外值得注意的是,在获取翻译字符串的过程中,需要将--keyword=pgettext:1c,2xgettext 让它知道这个函数的存在。
  • 我在使用这个函数时遇到了麻烦,首先:dcgettext的调用似乎不正确,我认为应该是dcgettext('messages', $contextString, 5)。然后:函数没有返回翻译,或者我的 PO 文件有问题。我asked a question about this issue here.
【解决方案2】:

在尝试使用 GNU xgettext 实用程序从源代码中提取字符串时,我遇到了上述 pgettext() 想法的一些问题。

起初它看起来会起作用。使用 --keyword 参数,我可以运行 xgettext 实用程序从测试脚本中提取这些上下文和消息字符串:

echo pgettext('Letter','mail');
echo pgettext('Letter','character');

并获得具有预期输出的 .pot 文件:

...
msgctxt "mail"
msgid "Letter"
msgstr ""

msgctxt "character"
msgid "Letter"
msgstr ""
...

但是 PHP *gettext() 函数不允许我传递上下文字符串 - 所以我无法获得翻译后的文本。

能够使用 GNU 实用程序让我的工作变得更轻松,所以我的解决方案是使用类似这样的东西:

function _c( $txt ) { return gettext( $txt ); }

echo "<P>", _c( "mail:Letter" ), "\n";
echo "<P>", _c( "character:Letter" ), "\n";

现在我运行 xgettext 实用程序

xgettext ... --keyword="_c:1" ...

反对我的测试脚本。这会生成一个带有简单 msgid 的 .pot 文件,可以通过 PHP gettext() 函数访问该文件:

...
msgid "mail:Letter"
...
msgid "character:Letter"
...

接下来我将 .pot 模板作为 .po 文件复制到各种 LC_MESSAGE 文件夹并编辑翻译文本:

...
msgid "mail:Letter"
msgstr "Russian outputs for Mail: \"письмо\""

msgid "character:Letter"
msgstr "Russian outputs for Letter of the Alphabet: \"буква\""
...

我的测试脚本有效:

...
Russian outputs for Mail: "письмо"

Russian outputs for Letter of the Alphabet: "буква" 
...

xgettext 的文档在这里: http://www.gnu.org/software/gettext/manual/html_node/xgettext-Invocation.html

(我仍然对 poedit 和“复数”文本有疑问,但这是另一个主题。)

【讨论】:

  • 感谢您的经验分享,这绝对是一个有趣的转折点,没想到gettext在php中造成这么大的麻烦
【解决方案3】:

对于像我这样使用 Poedit 的人,您需要关注。首先创建函数。我正在使用一个名为 _x 的文件,就像 WordPress 使用的文件一样:

if (!function_exists('_x')) {

function _x($string, $context)
{
  $contextString = "{$context}\004{$string}";
  $translation = _($contextString);
  if ($translation == $contextString)  
     return $string;
  return $translation;
}
}

然后在 poedit 上,您需要在 Sources 关键字选项卡上输入以下内容:

_x:1,2c
_

因此,当您需要使用上下文翻译时,您可以使用 _x 函数。例如:

<?php
echo    _x('Letter', 'alphabet');
echo    _x('Letter', 'email');
echo    _('Regular translation');

我从这些链接中获取了所有信息:

【讨论】:

    【解决方案4】:

    我制作了一个包来为 PHP 中缺少 pgettext 提供一个简单的解决方案。

    here

    你需要用composer require datalinx/gettext-context安装包,然后才能使用

    echo pgettext('Mail', 'Letter'); // Echoes: письмо
    echo pgettext('Character', 'Letter'); // Echoes: буква
    

    还实现了复数和域覆盖函数(npgettext、dpgettext、dnpgettext)。

    【讨论】:

      猜你喜欢
      • 2013-05-05
      • 1970-01-01
      • 2019-09-20
      • 1970-01-01
      • 1970-01-01
      • 2010-12-18
      • 1970-01-01
      • 2018-07-16
      • 2022-11-23
      相关资源
      最近更新 更多