14

我正在开发一个多语言 PHP Web 应用程序,我有很长的(-ish)文本需要用 gettext 翻译。这些是电子邮件模板(通常很短,但仍然有几行)和部分视图模板(较长的描述性文本块)。这些文本将包含一些简单的 HTML(例如粗体/斜体表示强调,可能是此处或此处的链接)。模板是捕获其输出的 PHP 脚本。

问题是 gettext 对于处理较长的文本似乎很笨拙。随着时间的推移,较长的文本通常会比短文本有更多的变化——我可以更改 msgid 并确保在所有翻译中更新它(当 msgid 很长时可能会做很多工作并且很容易出错),或者我可以保留msgid 不变,只修改翻译(这会在模板中留下误导性的过时文本)。此外,我看到了反对在 gettext 字符串中包含 HTML 的建议,但避免它会将单个自然文本分成很多块,这将是翻译和重组的更大噩梦,我也看到了反对的建议将 gettext 字符串不必要地拆分为单独的 msgid。

我看到的另一种方法是完全忽略这些较长文本的 gettext,并将这些块分隔在每个语言环境的外部子模板中,并仅包含当前语言环境的块。缺点是我将 gettext .po 文件和位于完全不同位置的单独模板之间的翻译工作分开。

由于此应用程序将在未来用作其他应用程序的起点,因此我正在尝试提出长期的最佳方法。在这种情况下,我需要一些关于最佳实践的建议。您是如何实施类似案例的?什么结果行得通,什么结果是个坏主意?

4

3 回答 3

11

这是我在一个流量非常大的网站上使用的工作流程,该网站有几十个长长的样式文本内容块,翻译成六种语言:

  1. 选择一种基于文本的标记语言(我们使用Markdown
  2. 对于长字符串,请使用固定的消息 ID,例如“About_page_intro_markdown”:
    • 描述文本的意图
    • 明确表示它将以降价格式解释
  3. 让我们的应用程序适当地呈现“*_markdown”字符串,确保只允许几个安全的 HTML 标记
  4. 为翻译人员构建一个工具:
    • 向他们展示他们实时渲染的 Markdown(有点像Markdown dingus
    • 让他们很容易看到文本的现在权威的基本语言翻译(因为它不再在msgid
  5. 教翻译人员如何使用新的工作流程

此工作流程的优点:

  • 消息 ID 不会一直更改
  • 因为翻译人员正在以安全的高级语法进行编辑,所以很难弄乱 HTML
  • 非技术翻译人员发现用 Markdown 编写与 HTML 相比非常容易

此工作流程的缺点:

  • 拥有静态不变的消息 ID 意味着文本中的变化需要在带外传输(无论如何我们都会这样做,因为长文本会引发有关语气或重点的问题)

我对这个工作流程为我们的网站运行的方式感到非常满意,并且绝对会推荐它,并再次使用它。开始花了几天时间,但它很容易构建、训练和发布。

希望这会有所帮助,并祝您的项目好运。

于 2011-11-15T20:23:19.277 回答
5

我刚刚遇到了这个特殊的问题,我相信我以一种优雅的方式解决了它。

问题:我们想在 PHP 中使用 Gettext,并使用主要语言字符串作为键翻译。但是,对于大块 HTML(使用 h1、h2、p、a 等),我要么必须:

  • 为每个包含内容的标签创建翻译。

或者

  • 将带有标签的整个块放在一个翻译中。

这些选项都没有吸引我,所以这就是我所做的:

  • 将简单字符串(“OK”、“Add”、“Confirm”、“My Awesome App”)保留为常规 Gettext .po 条目,以原始文本为键
  • 在 Markdown 中写入内容(大文本块),并将它们保存在文件中。示例文件是/homepage/content.md(主要/源文本)/homepage/content.da-DK.md、、/homepage/content.de-DE.md

  • 编写一个获取内容文件(针对当前语言环境)并解析它的类。然后我像这样使用它:

    <?=Template::getContent("homepage/content")?>

但是,动态大文本呢?简单的。使用模板引擎。我决定使用Smarty,并在Template课堂上使用它。

我现在可以在降价中使用模板逻辑.. !这有多厉害?!

然后是棘手的部分..

为了使内容看起来不错,有时您需要以不同的方式构建 HTML。考虑一个在其下方有 3 个“功能框”的活动区域。简单的解决方案:为活动区域准备一个文件,三个盒子各有一个。

但我可以做得更好。

我写了一个快速块解析器,所以我会将所有内容写入一个文件,然后分别渲染每个块。

示例文件:

[block campaign]
Buy this now!
=============

Blaaaah... And a smarty tag: {$cool}
[/block]

[block feature 1]
Feature 1
---------

asdasd you get it..
[/block]

[block feature 2] ...

这就是我在标记中呈现它们的方式:

<?php 
// At the top of the document...

// Class handles locale. :)
$template = Template::getContent("homepage/content", [
    "cool" => "Smarty variable! AWESOME!"
]);
?>

...

<title><?=_("My Awesome App")?></title>    

...

<div class="hero">
   <!-- Template data already processed! :) -->
   <?=$template->renderBlock("campaign")?>
</div>
<div class="featurebox">
   <?=$template->renderBlock("feature 1")?>
</div>
<div class="featurebox">
   <?=$template->renderBlock("feature 2")?>
</div>

恐怕我不能提供任何源代码,因为这是一个公司项目,但我希望你能明白。

于 2014-02-20T09:51:47.843 回答
3

gettext 并不是真正为翻译大段文本而设计的。

fwiw 我已经在 gettext 字符串中包含了基本的 HTML(strong、a 等),因为我相信我们的翻译人员知道他们在做什么(大部分是正确的)并且翻译会得到很好的测试。

我尝试过将文本分成每段一个字符串的方法。如果文本中间有一段英语,大致上看起来很奇怪。其中一个字符串发生了变化,这意味着我们必须等待翻译才能发布新版本,这让我们放慢了速度。从好的方面来说,翻译人员很容易看到文本的哪一部分发生了变化。这种方法适用于我尝试过的一个应用程序。

将一些文本拆分到外部位置也可以,但它会导致管理开销,而不仅仅是一两个 .po 文件,还有一大堆其他文本必须手动与英文版本进行比较并相应更新。如果您记得向您的翻译人员提供说明,说明英文版本的差异在哪里以及有什么不同,这是可行的。

我自己仍然没有接受任何一种方法。

于 2011-11-08T08:13:31.870 回答