15

In an extension I'm working on, I have a layout XML added via module's config.xml. This layout has some modifications to the frontend. Some of these blocks, however, belong to Magento core modules. The templates are all showing correctly as expected.

The templates I have packaged with the module itself are using the translation files of my own module. The templates packaged with Magento core show untranslated. If I add a translation file for the respective core module, then that translation file is used & the template shows translated.

Is there a way to make Magento use my module's translation file if it can't find any translation files for Magento core module? Is there anything else I can do here?

  • You can either add your translations to current theme translation file or use inline translation interface in backend. – Dmytro Zavalkin Apr 26 '13 at 14:57
  • I wanted to package translations with the extension itself, the above would require adding instructions for anyone who installs it. Is there any option where i can do it from the code? – Mridul Aggarwal Apr 26 '13 at 15:06
  • 4
    It depends on how translation is used in tempalte, $this->__() or Mage::helper('...')->__(). In fist case you can force block to use your translation helper. But I believe in general case the only option is data upgrade for core_translate table. Here internationalization qestions are described in details: blog.belvg.com/…. – Dmytro Zavalkin Apr 26 '13 at 15:10
  • See as well Avoid loss of translation when overwriting a block for an easier hands-on solution. – hakre Apr 16 '15 at 9:00
20

No matter how you approach it, your problem requires a "creative" solution, worthy of a developer note for subsequent devs/maintainers to use. First, some background, followed by a note, followed by an easy and I think reasonable solution at the end <-- tl;dr.

As Zyava pointed out, translation is subject to the module doing the translation. Templates render in block instances, and block instances have a module_name property which is used when invoking translation; ref Mage_Core_Block_Abstract::__() :

public function __()
{
    $args = func_get_args();
    $expr = new Mage_Core_Model_Translate_Expr(array_shift($args), $this->getModuleName());
    array_unshift($args, $expr);
    return Mage::app()->getTranslator()->translate($args);
}

The module_name property is (normally) derived on demand and based on class name (ref. ::getModuleName()):

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;
}

So, if the module_name property is already set, that module translation applies. For extant blocks from core layout, this property can be set via layout XML; for example:

<default>
    <action block="root" method="setModuleName">
        <name>Your_Module</name>
    </action>
</default>

Voilà! Your module CSV owns the translation for that instance. This could be an approach. Of course, there is still the sticky situation of other modules' translation being applied via module-specific helper in block instances (including template files of course), and it's always true for layout XML translations. Also, this approach will break the Disable Modules Output behavior, which uses the module_name param.

Solution

As it turns out, it's possible to specify multiple translation files for a module. It's not done in the core (each module only declares one .csv file), but the functionality is there in Mage_Core_Model_Translate:

public function getModulesConfig()
{
    if (!Mage::getConfig()->getNode($this->getConfig(self::CONFIG_KEY_AREA).'/translate/modules')) {
        return array();
    }

    $config = Mage::getConfig()->getNode($this->getConfig(self::CONFIG_KEY_AREA).'/translate/modules')->children();
    if (!$config) {
        return array();
    }
    return $config;
}

and

protected function _loadModuleTranslation($moduleName, $files, $forceReload=false)
{
    foreach ($files as $file) {
        $file = $this->_getModuleFilePath($moduleName, $file);
        $this->_addData($this->_getFileData($file), $moduleName, $forceReload);
    }
    return $this;
}

Because the files' contents are merged (I tested), it's possible to specify only those strings which you want to override in your custom CSV(s). For example, if you want to translate the Additional Information string on the product page (translated by the Mage_Catalog module), the following would work:

app/locale/Custom.csv:

"Additional Information","More Info, Dude"

In your module config - which should <depends /> on Mage_Catalog to ensure its contents merge after - the following will cause the Custom.csv translation pairs to merge on top of the original:

<frontend>
    <translate>
        <modules>
            <Mage_Catalog>
                <files>
                    <additional>Custom.csv</additional>
                </files>
            </Mage_Catalog>
        </modules>
    </translate>
</frontend>

The nice thing about this approach is that you can collect your overriding core translations in one file.

  • @Francesco It should. Clear translation cache? If it seems to not work, please post this as a new question (and link here for posterity). – benmarks Dec 17 '13 at 17:49
  • I confirm it work both $this>_ and with helper. you are right, it was my fault ( I have removed previous erroneous comment ) – Fra Dec 19 '13 at 15:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.