如何使模板中的字符串在出现的所有页面上都可翻译?


14

t()在* .tpl.php文件中有一些呼叫。举个例子,我说的是产品和product.tpl.php文件。

模板中的字符串只有在首次使用时才能被识别。Drupal.org上有一个关于此的线程,我发现它是准确的。遗憾的是,如果我转到http://example.com/pl/product/200,那么该字符串将保存在{locales_source}表中,其location字段设置为/pl/product/200

我需要我的用户能够使用本地化客户端模块的现场翻译工具进行翻译,这样他们才能在适当的上下文中真正看到他们正在翻译的内容。将源位置设置为/pl/product/200,ID为200的产品是唯一显示该字符串已被翻译的产品。更糟糕的是,如果我可以强迫用户翻译该特定产品,我还需要他们也能够翻译成俄语,并且没有将位置设置为的产品/ru/product/PID

有没有办法重新格式化数据库中的位置字符串,使所有字符串在l10n_client工具中的所有产品和所有语言上可见?

我尝试将其设置为:

  • ; sites/default/themes/mytheme/product.tpl.php
  • sites/default/themes/mytheme/product.tpl.php
  • sites/default/modules/mymodule/mymodule.module (生成主题数据的模块)

但这仅使它们对于翻译工具不可见。

我很确定这不是Localization client中的错误,它显示了告诉该字符串发生的字符串。而且看来,对于Drupal 7翻译系统来说,这也是“它的工作方式”-已经进行了讨论和报告,没有任何改变。所以这不是错误报告,我只是问如何处理我们必须处理的内容。


我说的是与数据模块无关的文本。我不想翻译产品,只翻译与产品本身无关的模板字符串,例如“产品图片库”模板上的“上一个-下一个”。

例如,模块返回15个缩略图,并且一次显示5个是主题的工作。以及上一个/下一个链接的需求alttitle属性。已翻译。但是我的模块不知道这一点。而且永远都不需要。


我不确定是否已经完全了解您的要求,但是使用所有语言爬网是否足够?您可以使用例如。xmlsitemap以生成多种语言的链接,然后使用wget或其他方式。骇人听闻的,但您确实说过是允许的(:
Andy

@Andy Localization Client允许用户在页面底部打开一个栏,并在看到它们时直接翻译该页面上显示的文本。我可以导出所有文本,但这并不是重点。
Mołot

1
我记得在drupal_set_message()和dpm()中,这些消息将排队等待下一个请求,例如从page.tpl.php中调用。这是因为模板通常在处理完消息后的请求中很晚才被处理。t()和本地化客户端的情况可能类似。
donquixote

好问题。好问题。
业余咖啡师

只是一个建议...如果您希望用户能够在任何时间以任何语言翻译tpl t()字符串,则可以使用翻译模板提取器(drupal.org/project/potx)提取这些字符串,并给他们原始.po文件,以便他们可以使用Poedit之类的工具进行翻译?(poedit.net)。当您将这些字符串显示为几个静态字符串时,每个翻译人员都会一次完成这项工作...
Kojo 2014年

Answers:


5

您的要求:
为了使我的网站能够
以经过身份验证的用户的多种语言工作,
我需要能够立即翻译使用t()函数在网站代码库中找到的所有翻译调用。

需求描述是否接近您的要求?


爬行者

就像有人说的那样-爬虫理论上可以遍历整个站点来强制注册所有t()调用。但是1)抓取工具不知道要抓取哪些页面;2)因此,我们不希望维护要爬网的页面列表;3)我们不想使用搜寻器。真是的 只是,eww。对?


问题

  1. 我们没有所有翻译字符串的列表。
  2. Drupal / PHP是一种动态语言,与C语言不同,后者是经过编译的。因此,我们无法举例:编译整个代码库,然后找到该函数的所有实例t(),然后在数据库中注册这些实例,然后一次翻译所有注册的实例t()。我认为这不是我们餐桌上的选择。
  3. 静态代码分析工具由于爬虫无助的原因而将无助。我t()在此文件中找到了这个。大!它使用什么URL?上下文是什么?

使用当前的工具(Drupal和一些contrib模块)以及当前的约束条件(依靠实时主题调用->模板文件-> t()调用)来解决问题,在这里看起来像是一条没有退出的通道。我们可能需要开箱即用。


我们需要的

  1. 我们需要一个数据源,一个模型,它可以告诉我我们当前拥有哪些翻译字符串,以及它们的上下文是什么-
  2. 主动数据模型。当前数据模型是反应性的(只要调用t()发生,该模型就会更新)。我们需要一种主动的数据模型-在这种模型中,应用程序会在t()实例真正被客户执行之前负责寻找实例。
  3. 我们需要上下文。t()单靠它并不能解决问题-因为-我们不知道我们正在翻译'foo',但是我们要翻译的目标语言取决于t()发生该错误的网址。即使我们可以t()使用包装程序调用将目标语言硬编码到调用中,也无法满足您的目的。

我已经确定了一些工具-如果有的话-可以解决我们的问题。使用这些工具,我们可以进入数据模型并说:给我所有包装t()好的尚未填充的字符串。现在插入这些翻译。谢谢。

下次客户来时,翻译就在那里。

我们将如何...构建这些工具?


约束条件

  1. 目标语言不能在模板上(由URL决定)。假设字符串必须支持任何语言。
  2. 转换后的字符串不能在模板上。翻译将保存在数据库中。

既然我已经对问题进行了更多的思考,并且确定了一些挑战和约束,那么我可以考虑研究现有的任何解决方案,或者制定任何定制的解决方案。

解决方案头脑风暴

我需要将“一切”联系在一起的东西。那实体呢?

  • 实体可以保存需要翻译的产品。
  • 实体可以提供需要翻译的产品与其上下文之间的关系(胶水)。
  • 实体可以在字段中指定产品的默认URL位置。
  • 令牌可用于指定产品将出现的替代位置(语言?)。
  • 实体为我们提供了所需的主动数据模型及其上下文。反过来,这又使我们可以执行以下操作:进入数据库,获取所有产品实体,如果没有针对字段X,Y和Z的转换字符串,则创建这些转换字符串。

然后/pl/product/200,当客户获取时,您将前往数据库,查找产品200,并获取已经存在的pl翻译。您也有该产品的标题和标题字段吗?翻译也应该在那里。

请注意,关于您使用的翻译模块,我在这里非常含糊和通用。您很可能最终会使用自己的翻译模块-很有可能是这种情况。到目前为止,我在Drupal中看到的所有翻译模型(截至D7,尚未查看D8)都是被动的,不是主动的。

简而言之

从理论上讲,存在构建所需内容的工具,实体是将所有内容捆绑在一起的关键组件:-数据(翻译字符串),-目标语言。对于产品语言,不必一定是实体本身,最好是分类词汇。或其他实体的通用分类法。-上下文。实体出现的URL。该URL将包含一个令牌,该令牌又将引用目标语言分类法。

使用这三种成分,您可以说:抓取所有product实体,前往 URL alias字段,获取分类标记,循环所有可能的术语组合,使用非常大的丑陋形式(或AJAX)将所有组合呈现给当前用户,并多步骤表单(类似这样),并且当当前登录的用户翻译产品200的各种语言时,请将这些语言保存到数据库中的某个位置

数据库中的某个位置可能是实体中的Field API字段,属于每个实体的settings字段(不完全是Field API,但它仍然可以保存数据)或用于此目的的单独表。我认为将数据保存到Entity中可以使代码和数据更加整齐和容易。


构建它:可能的解决方案

  • D8MI(Drupal 8多语言计划)
  • 定制代码:t()通过以编程方式查询和呈现可用的包及其相关主题挂钩实现,从而使t()在模板中提供“索引”翻译。

伪码

Foreach实体(类型为x),
查找所有语言(与产品关联的分类法或核心语言),
渲染该实体,
-为了检测到它是t()翻译字符串
-渲染调用theme(),该主题处理以下语言的多语言表示层产品,而不是产品数据模型本身。

结果:
-首次调用每种语言的渲染实体模板将返回每次调用的默认语言实现。
-现在,模板上的t()参数已缓存在Drupal中,可以进行翻译了(对于每种语言实例,而不是每种产品实例)。
-具有“翻译”角色的用户现在可以转到翻译界面,并翻译每种语言的所有可用t()参数。
-网站所有者无需等待客户访问每个产品页面或手动访问每个产品页面,因为这是通过编程方式完成的。

公开问题:
-什么是背景?如果我对每个“产品”实体束都进行了对theme()的编程调用,它是否记录了进行调用的位置?它是否记录节点的URL?可以更改“上下文”吗?上下文记录在哪里?当您拥有“动态”模板时,即每种产品有多个模板时,会发生什么?如何检测这些变化?

与往常一样,理论化和伪代码仅适用于头脑风暴。但是在开发中,直到我们开始进行原型设计之前,我们几乎不知道我们真正要面对什么。因此,在草拟了两个约束,可能的解决方案以及可能的问题或疑问后,我现在可以继续实施概念证明或工作原型。上面的一些悬而未决的问题只能以这种方式回答,而我们最早的原型(无论成功或失败),我们都可以开始回答其中的一些问题-或完全改变方法。敬请期待〜


1
即使没有阅读整篇文章,这种回答也应该得到赞扬
Oleg Videnov

关键是-声称它可以满足我对Drupal 7的需求的工具已经存在。Drupal用不良的元数据保存这些字符串只是一个问题。但是一旦收集到字符串,我可以在db中更改所说的元数据,没问题。我只需要知道将它们设置为什么,工具就可以看到它。或者至少我相信这是我所需要的。最重要的是:我不想翻译产品,而只是翻译与产品本身无关的模板字符串,例如产品图片库模板上的“一步-下一步 ”。
Mołot

2

好的,花更多的时间在本地化客户端和实体转换模块上来重现相同的场景。由于此答案与我之前的答案完全不同,因此添加为单独的注释:

  1. 在一个/第一个节点中为语言添加的翻译可用于所有节点。

    这是一个例子:

    • 如果我添加与nid 200相同类型的新产品并访问新节点的pl转换(例如pl / product / 204),我将在pl / product / 200中看到相同的转换字符串。

    • 唯一的区别是它没有出现在本地化客户端中。我们可以在模块的发布队列中请求此功能,但是由于翻译不是特定于当前页面,并且会影响所有页面(即pl / product / 200和pl / product / 204),因此会带来更多的混乱。

    • 如果两个节点是由两个不同的人创建的,而后一个节点想要更改转换,则它们必须使用接口转换。

  2. 在本地化客户端中,该字符串可用于您为同一节点访问的第一种语言

    这是一个例子:

    • 如果我添加新产品nid 199并创建“ pl”语言的翻译(nid 200)和“ rs”语言的翻译(nid 201),则只能在“ pl”页面上看到字符串,而不能在“ rs”页面上看到字符串。同样,这看起来像是本地化客户端模块中的限制。

1

您在模板或模块文件级别添加翻译字符串的方法可能适用于界面翻译UI,但不适用于本地化客户端。

显然,当您拥有俄语版本的产品200时,它将是一个新节点,例如/ ru / product / 201,您可以在其中使用本地化客户端进行翻译。

只是想一想:在界面翻译UI中寻找可以为所有语言翻译的字符串,并在真正必要时要求客户翻译产品级别。这是一个例子:

“这是类别栏的产品foo”

如果我们确定除'foo'和'bar'以外的其他地方可以通用,我们可以添加

$vars['product_title'] = t('This is product @product of category @category')

在预处理中。

.tpl.php文件将是

<?php t($product_title, array('@product' => t('foo'),  '@category' => t('bar')); ?>

更多有关title图像旋转器中箭头的文字。我的模块不在乎主题如何显示15张图像。主题一次显示5个,其中需要alt和的“上一个”和“下一个”箭头title需要翻译。每当我的前端发生变化时,都可以更改模块,但是当然不需要。这些字符串与模块本身无关。最后但并非最不重要的一点是,我可能根本不知道主题更改中的字符串。或无法将它们迁移到模块中。
Mołot

恕我直言,这种情况应该在界面翻译UI中而不是在本地化客户端中处理。
vijaycs85 2014年

本地化客户端旨在允许“在看到问题时在您的网站上修复翻译”。-为什么它不适用于模板文件?tpl中的字符串对出现的上下文更加敏感(如果有的话)。
Mołot

1

使用转换模板提取器的 AFAIK,您可以在t()函数的所有调用中提取字符串。

Translation模板提取器为Drupal提供了基于Web的和基于命令行的Gettext转换模板提取器接口,以及可重复使用的API,以查找可翻译的字符串和可翻译性错误。该工具可在 http://localize.drupal.org/的后台使用,也可作为Drupal.org项目版本的解析机。

阅读本文如何翻译模块?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.