Как реализовать переводы в дизайн шаблона пакета CSV? Как работает echo $ this -> __ ('Text')?

29

У меня есть настройка дизайна пакета, например, так:

design/frontend/package_name/theme_name/locale/

под которым у меня есть

de_DEи en_GBт.д., под которым у меня есть соответствующие translate.csvфайлы с различными строками:"Key", "Translation"

Я пытаюсь реализовать различные строки в моей теме, используя echo $this->__('Text')

Тем не менее, это не похоже на работу (я вижу только строку внутри ('Text')отображаемого). Я думаю, что мне не хватает фундаментального понимания того, когда Magento извлекает строки из CSV для перевода. Может кто-нибудь объяснить, как заставить эти CSV-файлы работать?

waffl
источник
Какую версию Magento вы используете?
Philwinkle
Я использую Magento v: 1.7.0.2
waffl
Вы вызываете это за пределами обычного файла шаблона magento? Возможно, вам нужно вызвать вспомогательный класс и сделать его чем-то вроде <? Php echo Mage :: helper ('core') -> __ ('Text'); ?> Также попробуйте включить «Перевести на
линию» в веб-интерфейсе

Ответы:

84

TL; DR

Если вас не интересуют подробности того, как работает перевод, перейдите к разделу «
Что проверить, если ваш перевод не работает » ниже, особенно в подразделе «
Решение для конфликтов при переводе модуля» .

Обзор перевода на Magento

Magento определяет приоритеты источников переводов (от высшего к низшему):

  1. БД ( core_translateтаблица)
  2. translate.csvФайл темы
  3. Эти app/locale/*/*.csvфайлы

Как строится массив перевода?

Модульные переводы

Сначала анализируются все файлы, на app/locale/*/*.csvкоторые есть ссылки из etc/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запись. Если он не найдет его, он вернется к переводу ключа 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. Если все предыдущие пункты не являются причиной, должен быть конфликтующий перевод из другого модуля. (Решение: см. Ниже)

Решение для конфликтных ситуаций модуля Scope

Если вы обнаружите, что окончательный вариант верен, просто добавьте перевод во второй раз translate.csv с помощью области модуля модуля, выполняющего перевод.
В этом примере, если вы всегда хотели AAAпереводить как с DDDпомощью перевода темы, вы можете сделать это в вашем translate.csv:

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

На практике я добавляю область действия модуля к переводу только в случае конфликта, то есть, если перевод не работает.

Дополнительные замечания

Встроенный перевод

Функция встроенного перевода в Magento также добавляет пользовательские переводы в core_translateтаблицу, используя префикс области видимости модуля.

Обратная совместимость

Приоритет переводов тем был выше, чем переводы базы данных до версии 1.3 или около того.

Перевод XML

Magento иногда оценивать translate=""аргументы в config.xml, system.xmlи компоновках XML для перевода значений дочернего узла.
В этих случаях можно указать вспомогательный класс, используя module=""аргумент, чтобы указать модуль для области перевода.
Если moduleв XML не указан аргумент, core/dataпомощник используется для перевода значений дочерних узлов.

Дальнейшая информация

Признаюсь, что в этом посте я замалчивал некоторые детали процесса перевода Magento, но только потому, что не хочу слишком много информации.

  • Некоторые технические детали при построении массива перевода
  • Возможность использования дополнительных файлов перевода для модулей
  • Сохранить область просмотра для core_translateзаписей
  • Плюсы и минусы с использованием разных методов перевода

Пожалуйста, задайте отдельный вопрос, если требуется дополнительная информация.

Vinai
источник
1
Хорошо, мне невероятно жаль всех, но кто-то еще включил кэши, не сказав мне ... Возможно, в тот момент, когда я начал работать над переводами. Вздох. Эта информация была невероятно полезной для моего понимания процесса перевода в Magento. Большое спасибо, это определенно отвечает на все мои вопросы о том, как __()работает эта функция.
вафля
Довольно хороший обзор архитектуры перевода Magento также можно найти здесь: gist.github.com/antonmakarenko/7538216
thdoan
@ Винай, отличный ответ. Это действительно помогло мне решить проблему перевода я отправил вопрос на здесь . Удивительно, но Mage_Tax конфликтовал с переводами моей темы, что, кажется, противоречит тому, как Magento предназначен для определения приоритетов переводов
Холли,
14

Источники перевода

Переводы объединяются из разных источников: переводы модулей из соответствующих файлов XML, переводы тем translate.csvиз текущей темы и встроенные переводы из базы данных.

Переводы могут быть строго специфичными для модуля (действительны только внутри модуля), это всегда имеет место для встроенных переводов и, необязательно, для тематических переводов. Для этого вы должны определить их с префиксом модуля в translate.csv:

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

Переводы из модулей (например Mage_Catalog.csv) являются строго специфичными для модуля, если включен РЕЖИМ РАЗВИТИЯ. В противном случае перевод первого загруженного модуля используется глобально для всех модулей, у которых нет собственного перевода текста.

Я собрал блок-схему, которая показывает, как каждый текст из разных источников объединяется в массиве перевода:

Перевод слияния data это массив перевода

Дело злого края

Если переведенная строка равна непереведенной строке, перевод игнорируется. На первый взгляд это звучит как полезная оптимизация, но таким образом вы не можете легко перевести строку, неизменную в одном модуле и измененную в другом модуле, потому что измененный перевод будет единственным и станет глобальным.

Поиск перевода

Для какого модуля ищется перевод, зависит от модуля класса, для которого __()был вызван метод . Затем поиск в массиве перевода выглядит следующим образом:

Поиск перевода data это массив перевода

Определение области

Есть возможность поменять модуль для одного класса, что особенно полезно для блоков и помощников. Рекомендуется всегда явно указывать имя модуля при переписывании базового класса. Как это работает, зависит от помощников, блоков и контроллеров (по состоянию на 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, layout) вы можете указать, следует ли преобразовывать узлы с помощью translateатрибута. Вы также должны добавить moduleатрибут, чтобы указать область, но здесь значение должно быть псевдонимом помощника , а не именем модуля, как указано выше.

<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может быть любой строкой, но должна быть глобально уникальной. translateИ moduleатрибуты используются как в других файлах XML. Значение messageи его перевод добавляются в объект JS Translator.

Поиск проблемы

Даже если вы знаете все сложные правила, иногда трудно понять, почему какой-то перевод работает как есть (или не работает). Чтобы сделать это проще, я разработал модуль «Советы по переводу», который показывает, откуда переводы:

Получите это здесь: https://github.com/schmengler/TranslationHints

Скриншот: Советы по переводу


На основе моих сообщений в блоге и слайдов по теме:

Фабиан Шменглер
источник
2
Я надеюсь, что я не рассылаю спам, упомянув, что мой бесплатный модуль Yireo EmailOverride позволит также размещать файлы пользовательских модулей CSV в теме. Не только translate.csv.
Джис Рейтсма
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
Вы были правы, кто-то включил кеш, не сказав мне. Ой, мои извинения и спасибо за информацию!
вафля
3
@waffl Не нужно извиняться - я думаю, что каждый разработчик Magento делает это, по крайней мере, один раз в неделю.
Алан Шторм