如何在设计模板包CSV中实现翻译?echo $ this-> __('Text')如何工作?


29

我有一个像这样的设计包设置:

design/frontend/package_name/theme_name/locale/

在我之下

de_DEen_GB等等,在这些translate.csv文件下,我具有带有各种字符串的相应文件:"Key", "Translation"

我正在尝试使用以下方法在主题中实现各种字符串 echo $this->__('Text')

但是,它似乎不起作用(我只看到('Text')显示的字符串)。我想我对Magento何时从CSV中提取字符串进行翻译缺乏基本了解。有人可以解释一下如何使这些csv文件工作吗?


您正在运行哪个版本的Magento?
philwinkle

我使用的Magento五:1.7.0.2
waffl

您是在普通的magento模板文件之外调用此文件吗?也许您需要调用helper类并使它类似于<?php echo Mage :: helper('core')-> __('Text');。?>还尝试在系统>配置>开发人员
SaveTheMage中,

Answers:


84

TL; DR

如果您对翻译的工作方式的细节不感兴趣,请跳过以下内容,直到下面的
“如果翻译不起作用应检查哪些内容” 部分,尤其是“
模块范围翻译冲突的解决方案 ”小节。

Magento翻译概述

Magento优先考虑翻译来源(从最高到最低):

  1. DB(core_translate表)
  2. 主题translate.csv文件
  3. app/locale/*/*.csv文件

如何构建翻译数组?

模块翻译

首先app/locale/*/*.csvetc/config.xml分析从活动模块文件中引用的所有文件。这是该过程的演练:
假设Magento找到以下config.xml部分:

<!-- excerpt from Mage/Catalog/etc/config.xml -->
<frontend>
    <translate>
        <modules>
            <Mage_Catalog>
                <files>
                    <default>Mage_Catalog.csv</default>
                </files>
            </Mage_Catalog>
        </modules>
    </translate>
</frontend>

在该文件中,为当前商店视图配置的语言环境指定了以下转换:

"AAA","BBB"

在这种情况下,Magento在转换数组中创建以下记录:

array(
    "AAA" => "BBB",
    "Mage_Catalog::AAA" => "BBB"
)

第二个值是“ 模块范围转换”。带前缀的模块名称来自包含转换文件声明的config XML节点。

如果通过再次指定相同的转换第二模块文件,例如,在Some_Module.csv翻译的"AAA","CCC",它将不会覆盖"AAA"设置。相反,它将仅添加带有第二个模块名称的新记录"Some_Module::AAA" => "CCC"

如果启用了开发人员模式,则如果在另一个模块转换中找到具有相同键的第二条记录,它甚至会取消"AAA"记录。这使得在开发过程中更容易发现模块翻译冲突。

主题翻译

其次,从translate.csv主题后备中第一个文件加载的当前语言环境的翻译仅替换了翻译数组中的现有记录。
因此,继续前面的示例,一条translate.csv记录"AAA","DDD"将导致以下翻译数据:

array(
    "AAA" => "DDD", // This is overwritten by the translate.csv file
    "Mage_Catalog::AAA" => "BBB",
    "Some_Module::AAA" => "CCC"
)

当然,translate.csv带有新转换键的中的记录只是添加到数组中。

数据库翻译

从翻译core_translate表基本上都合并到翻译阵列就像主题的翻译。
模块记录或主题转换中的现有键将被数据库记录覆盖,并添加新的键。

翻译查询

__()调用该方法时,Magento首先在数组中查找与当前模块匹配的转换。
当前模块由__()调用该类的类名称确定。例如,在块中,负责的方法如下所示:

// Excerpt from Mage/Core/Block/Abstract.php
public function getModuleName()
{
    $module = $this->getData('module_name');
    if (is_null($module)) {
        $class = get_class($this);
        $module = substr($class, 0, strpos($class, '_Block'));
        $this->setData('module_name', $module);
    }
    return $module;
}

助手和控制器中的方法将相应地工作。

查找方案示例

例如,可以说$this->__('AAA')在模板文件中被调用。如果相关块的类型为Mage_Core_Block_Template,则Magento将首先检查Mage_Core::AAA记录。如果找不到,它将退回到key的翻译AAA
在示例场景中,这将导致翻译DDD(来自translate.csv文件)。

在不同的情况下,关联的块可能是Mage_Catalog_Block_Product_View。在这种情况下,Magento首先检查翻译记录Mage_Catalog::AAA,然后找到翻译AAA

因此,实际上,模块作用域翻译的优先级高于任何通用翻译。使用哪种转换取决于类从调用__()方法的哪个模块开始。

如何检查翻译是否正常

如果translate.csv未使用文件翻译,请遵循以下清单:

  1. 翻译缓存是否已关闭/刷新?(解决方案:清除缓存)
  2. translate.csv文件确实在当前商店的主题回退中吗?(解决方案:修复主题配置)
  3. core_translate表格中的翻译记录是否有冲突?(解决方案:从中删除有冲突的记录core_translate
  4. 如果不是所有上述要点,则必须来自其他模块的翻译有冲突。(解决方案:请参见下文)

模块范围翻译冲突的解决方案

如果您发现最终的情况是真实的,只是第二次加翻译,以您translate.csv 模块做翻译的模块范围。
在这个例子中,如果你总是希望AAA被译为DDD通过主题翻译,你可以在你做到这一点translate.csv

"AAA","DDD"
"Mage_Catalog::AAA","DDD"
"Some_Module::AAA","DDD"

在实践中,只有在发生冲突(即,翻译不起作用)时,才将模块作用域添加到翻译中。

附加条款

内联翻译

Magento的内联翻译功能还core_translate使用模块作用域前缀将自定义翻译添加到表中。

向后兼容

过去,主题翻译的优先级高于数据库翻译,直到Magento 1.3或更高版本。

XML转换

Magento有时会评估中的translate=""参数config.xmlsystem.xml并布局XML来转换子节点值。
在这种情况下,可以使用module=""参数为转换范围指定模块来指定帮助程序类。
如果module在XML中未指定任何参数,core/data则使用助手来转换子节点值。

更多信息

我承认我在这篇文章中掩盖了Magento翻译过程的一些细节,但这仅仅是因为我不想提供太多信息。

  • 构建转换数组时的一些技术细节
  • 为模块使用其他翻译文件的可能性
  • 存储core_translate记录的视图范围
  • 使用不同翻译方法的利弊

如果需要更多信息,请询问另一个问题。


1
好的,非常抱歉,每个人,但是其他人没有告诉我就打开了缓存...大概是在我开始翻译的那一刻。叹。但是,这些信息对我理解Magento的翻译过程非常有帮助。非常感谢,这肯定回答了我对__()函数如何工作的所有疑问。
waffl

也可以在这里找到Magento的翻译体系结构的很好概述:gist.github.com/antonmakarenko/7538216
thdoan 2014年

@Vinai,一个很好的答案。这确实帮助我解决了翻译问题,我在这里发表了一个问题。令人惊讶的是,Mage_Tax与我主题的翻译存在冲突,这似乎与Magento的翻译优先顺序相反
Holly,

14

翻译来源

:翻译来自不同来源的合并模块的翻译从各自的XML文件,主题翻译translate.csv当前主题的,以及在线翻译从数据库中。

翻译可以严格地是模块特定的(仅在模块内有效),内联翻译和主题翻译通常都是这种情况。为此,您必须在translate.csv中使用模块前缀定义它们:

"Mage_Catalog::Add to cart","In die Einkaufstüte legen"

Mage_Catalog.csv如果打开了DEVELOPER MODE,则模块(如)的转换仅严格地针对模块。否则,第一个加载的模块的翻译会全局用于所有不具有文本翻译功能的模块。

我组装了一个流程图,该流程图显示了来自不同来源的每个文本如何在翻译数组中合并:

翻译合并 data 是翻译数组

邪恶边缘案例

如果翻译后的字符串等于未翻译的字符串,则忽略翻译。乍一看,这听起来像是有用的优化,但是通过这种方式,您将无法轻松转换在一个模块中未更改而在另一个模块中已更改的字符串,因为更改后的转换将是唯一的且成为全局的。

翻译查询

针对哪个模块查找翻译,取决于已在其上__()调用方法的类的模块。然后,在转换数组中的查找如下:

翻译查询 data 是翻译数组

范围定义

可以为一个类更改模块,这对于块和助手特别有用。最佳实践是在重写核心类时始终显式设置模块名称。它的工作方式在Helper,Block和Contollers之间有所不同(从Magento CE 1.9.1开始)

块示例:

class IntegerNet_AwesomeModule_Block_Catalog_Product extends Mage_Catalog_Block_Product
{
    public function getModuleName()
    {
        return 'Mage_Catalog';
    }
}

对于块,还可以module_name在布局XML中设置参数:

<block type="integernet_awesomemodule/catalog_product" name="test" module_name="Mage_Catalog" />

帮手示例:

class IntegerNet_AwesomeModule_Helper_Catalog extends Mage_Catalog_Helper_Data
{
    protected $_moduleName = 'Mage_Catalog';
}

对于前端控制器,您可以_realModuleName为管理控制器设置属性,_usedModuleName(为保持一致性,可以)

其他翻译方法

在XML文件(config.xml,system.xml,布局)中,可以指定是否应使用translate属性转换节点。您还应该添加module属性以指定范围,但是这里的值必须是helper别名,而不是上面的模块名称。

<one_column module="page" translate="label">
    <label>1 column</label>
    <template>page/1column.phtml</template>
    <layout_handle>page_one_column</layout_handle>
    <is_default>1</is_default>
</one_column>

在JavaScript中,您可以使用Translator全局可用的对象:

Translator.translate('Please wait, loading...');

但是您必须将要在JavaScript中使用的翻译提供给翻译器对象。这是通过模块目录中的jstranslator.xml文件完成etc的。

<?xml version="1.0"?>
<jstranslator>
    <loading translate="message" module="core">
        <message>Please wait, loading...</message>
    </loading>
</jstranslator>

loading可以是任何字符串,但必须是全局唯一的。将translatemodule属性被用作其它XML文件。的值message及其转换被添加到JS Translator对象中。

故障排除

即使您了解所有复杂的规则,有时也很难理解为什么某些翻译按原样进行(或不进行)。为了简化此过程,我开发了一个“翻译提示”模块,该模块显示翻译的来源:

在这里获取:https : //github.com/schmengler/TranslationHints

屏幕截图: 翻译提示


基于我的博客文章和有关该主题的幻灯片:


2
我希望我不会因为提到我的免费Yireo EmailOverride模块而允许发送垃圾邮件,该模块也允许将自定义CSV模块文件也放置在主题中。不只是translation.csv。
Jisse Reitsma,2015年

6

您是否清除了缓存?

系统是否设置为要测试的文件的语言环境?

Magento可以在加载主题翻译时找到它要查找的文件(一些临时的var_dump;退出;语句应该有所帮助。)

#File: app/code/core/Mage/Core/Model/Translate.php
protected function _loadThemeTranslation($forceReload = false)
{
    $file = Mage::getDesign()->getLocaleFileName('translate.csv');
    $this->_addData($this->_getFileData($file), false, $forceReload);
    return $this;
}

_getTranslatedString方法可以在数据数组中找到所需的内容吗?

#File: app/code/core/Mage/Core/Model/Translate.php
protected function _getTranslatedString($text, $code)
{
    $translated = '';
    if (array_key_exists($code, $this->getData())) {
        $translated = $this->_data[$code];
    }
    elseif (array_key_exists($text, $this->getData())) {
        $translated = $this->_data[$text];
    }
    else {
        $translated = $text;
    }
    return $translated;
}

没有一个缓存处于活动状态,我不确定我的系统是否设置为语言环境,但是翻译会相应地在某些模板文件中工作(通过更改商店)。例如,我中的字符串可以translate.csv正确翻译,/app/design/frontend/package_name/default/template/catalog/product/view.phtml但不能正确翻译/app/design/frontend/package_name/default/template/page/html/topmenu.phtml
waffl 2013年

您说得对,有人打开了缓存,没有告诉我。糟糕,很抱歉,谢谢您提供的信息!
waffl

3
@waffl无需道歉-我认为每个Magento开发人员每周至少要做一次。
艾伦·风暴
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.