Understanding Magento Translations

This article aims to assist you in understanding Magento Translations and how they are used to support multiple language views within Magento.

The __()

If you’ve ever delved into Magento templating system and attempted to modify the files you’ll have probably come across pieces of code that look like the following.

echo $this->__('Proceed to Checkout');

Or lines that use the same method via Magento’s core helper class.

echo $this->helper('core')->__('Add to cart');

These lines are in fact part of Magento’s excellent translation functionality and are used to support internationalisation. The __() part of the code should look familiar if you have a basic understanding of PHP. It is of course a method.

But where exactly is the method __() located and what does it do?

This method comes from one of Magento’s core helper classes, Mage_Core_Helper_Abstract and it used to translate strings.

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

An instance of Mage_Core_Model_Translate is returned via the getTranslator() method.

public function getTranslator() {
    if (!$this->_translator) {
        $this->_translator = Mage::getSingleton('core/translate');
    }
    return $this->_translator;
}

So here we are returning a singleton of the core translator class, which is found in Mage_Core_Model_Translate. We then have the translate() method.

public function translate($args) {
    $text = array_shift($args);

    if (is_string($text) && ''==$text || is_null($text)
        || is_bool($text) && false===$text
        || is_object($text) && ''==$text->getText()) {
        return '';
    }
    if ($text instanceof Mage_Core_Model_Translate_Expr) {
        $code = $text->getCode(self::SCOPE_SEPARATOR);
        $module = $text->getModule();
        $text = $text->getText();
        $translated = $this->_getTranslatedString($text, $code);
    }
    else {
        if (!empty($_REQUEST['theme'])) {
            $module = 'frontend/default/'.$_REQUEST['theme'];
        } else {
            $module = 'frontend/default/default';
        }
        $code = $module.self::SCOPE_SEPARATOR.$text;
        $translated = $this->_getTranslatedString($text, $code);
    }

    //array_unshift($args, $translated);
    //$result = @call_user_func_array('sprintf', $args);

    $result = @vsprintf($translated, $args);
    if ($result === false) {
        $result = $translated;
    }

    if ($this->_translateInline && $this->getTranslateInline()) {
        if (strpos($result, '{{{')===false || strpos($result, '}}}')===false || strpos($result, '}}{{')===false) {
            $result = '{{{'.$result.'}}{{'.$translated.'}}{{'.$text.'}}{{'.$module.'}}}';
        }
    }

    return $result;
}

Translation Methods

There are three methods of using translations within Magento.

  • Inline translation saving translations to the core_translate database table
  • Theme-specific translations via the use of creating a theme.csv file
  • Module translations that reside in the app/locale directory.

The code within the if statements give us a clue of what translation type Magento is checking.

$module = $text->getModule();

The line above tells us that the translation may belong in a module .csv file, such as in app/locale/[lang]_[ISO]/.

Following on from that:

if (!empty($_REQUEST['theme'])) {

gives us a clue that the translation may belong in a theme .csv file, such as in app/design/frontend/package/theme/locale/[lang]_[ISO]/translate.csv.

The line:

if ($this->_translateInline && $this->getTranslateInline()) {

gives us a clue that the translation may belong in the core_translate database table.

If you’ve studied Magento translations before, you’ll know that inline translation takes the highest priority, followed by theme translation and then module translation. This is because the translate inline if statement is placed underneath the theme and module if conditionals, and therefore this code is executed last.

The getTranslatedString() method is responsible for returning the value of the translated string.

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

By understanding Magento translations well, you should be able to grasp the concepts of creating and updating translations within the application.

Ensure that you place the translations in the correct location, along with refreshing the in-built translation cache, and you should have no problem.

Note: This article is based on Magento Community/Open Source version 1.9.