¿Cómo implementar traducciones en el paquete de plantillas de diseño CSV? ¿Cómo funciona echo $ this -> __ ('Texto')?

29

Tengo una configuración de paquete de diseño como esta:

design/frontend/package_name/theme_name/locale/

bajo el cual tengo

de_DE, en_GBetc., bajo el cual tengo los translate.csvarchivos correspondientes con las diferentes cadenas:"Key", "Translation"

Estoy tratando de implementar varias cadenas en mi tema usando echo $this->__('Text')

Sin embargo, no parece funcionar (solo veo la cadena dentro de la que se ('Text')muestra). Creo que me falta una comprensión fundamental de cuándo Magento extrae cadenas del CSV para traducirlas. ¿Alguien puede explicar cómo hacer que estos archivos csv funcionen?

waffl
fuente
¿Qué versión de Magento estás ejecutando?
philwinkle
Estoy usando Magento v: 1.7.0.2
waffl
¿Está llamando a esto fuera de un archivo de plantilla magento normal? Tal vez necesite llamar a la clase de ayuda y hacerla algo así como <? Php echo Mage :: helper ('core') -> __ ('Text'); ?> Intente también habilitar "Traducir en línea" en Frontend en Sistema> Configuración> Desarrollador
SaveTheMage

Respuestas:

84

TL; DR

Si no está interesado en los detalles de cómo funciona la traducción, salte el contenido a la sección
Qué verificar si su traducción no funciona a continuación, especialmente la subsección
Solución para conflictos de traducción del alcance del módulo .

Descripción general de la traducción de Magento

Magento prioriza las fuentes de traducción (de mayor a menor):

  1. DB (la core_translatemesa)
  2. El translate.csvarchivo de tema
  3. Los app/locale/*/*.csvarchivos

¿Cómo se construye la matriz de traducción?

Traducciones de módulos

Primero se analizan todos los archivos a partir de los archivos de app/locale/*/*.csvmódulos activos etc/config.xml. Aquí hay un tutorial del proceso:
Suponga que Magento encuentra la siguiente config.xmlsección:

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

Y en ese archivo, se especifica la siguiente traducción para la configuración regional configurada para la vista de la tienda actual:

"AAA","BBB"

En estas circunstancias, Magento crea los siguientes registros en la matriz de traducción:

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

El segundo valor es la Traducción del alcance del módulo . El nombre del módulo prefijado se toma del nodo XML de configuración que contiene la declaración del archivo de traducción.

Si la misma traducción es especificada nuevamente por un segundo archivo de módulo , por ejemplo, en Some_Module.csvla traducción es "AAA","CCC", NO SOBRESCRIBIRÁ la "AAA"configuración. En cambio, solo agregará un nuevo registro con el segundo nombre del módulo "Some_Module::AAA" => "CCC".

Si el modo desarrollador está habilitado, incluso desarmará el "AAA"registro si encuentra un segundo registro con la misma clave en la traducción de otro módulo. Esto hace que sea más fácil detectar conflictos de traducción de módulos durante el desarrollo.

Traducciones de temas

En segundo lugar, las traducciones cargadas desde el primer translate.csvarchivo en la reserva de temas para la configuración regional actual simplemente reemplazan los registros existentes en la matriz de traducción.
Continuando con el ejemplo anterior, un translate.csvregistro "AAA","DDD"llevaría a los siguientes datos de traducción:

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

Por supuesto, los registros en las translate.csvnuevas claves de traducción simplemente se agregan a la matriz.

Traducciones de bases de datos

Las traducciones de la core_translatetabla se fusionan básicamente en la matriz de traducción al igual que las traducciones de temas.
Las claves existentes del módulo o las traducciones de temas se sobrescriben con los registros de la base de datos, y se agregan otras nuevas.

Búsqueda de traducción

Cuando __()se llama al método, Magento primero busca una traducción en una matriz que coincida con el módulo actual.
El módulo actual está determinado por el nombre de la clase en la que __()se llama la clase. Por ejemplo, en bloques, el método responsable se ve así:

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

Los métodos en Helpers and Controllers funcionan de manera correspondiente.

Ejemplos de escenarios de búsqueda

Por ejemplo, digamos que $this->__('AAA')se llama en un archivo de plantilla. Si el bloque asociado tiene el tipo Mage_Core_Block_Template, Magento primero buscará un Mage_Core::AAAregistro. Si no lo encuentra, recurrirá a la traducción de la clave AAA.
En el escenario de ejemplo, esto dará como resultado la traducción DDD(del translate.csvarchivo).

En un escenario diferente, el bloque asociado podría ser Mage_Catalog_Block_Product_View. En este caso, Magento primero buscaría un registro de traducción Mage_Catalog::AAAy buscaría la traducción AAA.

En efecto, las traducciones del alcance del módulo tienen una prioridad más alta que cualquier traducción genérica . La traducción utilizada depende del módulo de la clase desde que se llama al __()método.

Qué verificar si su traducción no funciona

Si translate.csvno está utilizando su traducción de un archivo, siga esta lista de verificación:

  1. ¿El caché de traducción está apagado / actualizado? (Solución: borrar el caché)
  2. ¿Está el translate.csvarchivo realmente en el tema de reserva para la tienda actual? (Solución: arreglar la configuración del tema)
  3. ¿Hay un registro conflictivo para la traducción en la core_translatetabla? (Solución: elimine el registro conflictivo de core_translate)
  4. Si todos los puntos anteriores no son la causa, debe haber una traducción conflictiva de un módulo diferente. (Solución: ver abajo)

Solución para conflictos de traducción del alcance del módulo

Si encuentra que el caso final es verdadero, simplemente agregue la traducción por segunda vez translate.csv con el alcance del módulo que realiza la traducción.
En el ejemplo, si siempre quiso AAAser traducido como a DDDtravés de la traducción del tema, puede hacerlo en su translate.csv:

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

En la práctica, solo agrego el alcance del módulo a la traducción si hay un conflicto, es decir, si una traducción no funciona.

Notas adicionales

Traducción en línea

La función de traducción en línea de Magento también agrega las traducciones personalizadas a la core_translatetabla utilizando el prefijo de alcance del módulo.

Compatibilidad con versiones anteriores

La prioridad de las traducciones de temas solía ser mayor que las traducciones de la base de datos hasta la versión 1.3 de Magento más o menos.

Traducción XML

Magento veces evaluar translate=""argumentos en config.xml, system.xmly XML diseño para traducir los valores de nodo secundario.
Se puede especificar una clase auxiliar en esos casos utilizando el module=""argumento para especificar el módulo para el alcance de la traducción.
Si no modulese especifica ningún argumento en el XML, el core/dataayudante se utiliza para traducir los valores del nodo secundario.

Más información

Confieso que pasé por alto algunos detalles del proceso de traducción de Magento en esta publicación, pero solo porque no quiero demasiada información.

  • Algunos detalles técnicos mientras se construye la matriz de traducción
  • La posibilidad de utilizar archivos de traducción adicionales para módulos
  • Alcance de la vista de la tienda para core_translateregistros
  • Pros y contras utilizando los diferentes métodos de traducción.

Haga una pregunta por separado si se requiere más información.

Vinaí
fuente
1
OK, lo siento muchísimo, pero alguien más encendió los cachés sin decirme ... Probablemente en el momento en que empecé a trabajar en las traducciones. Suspiro. Sin embargo, esta información fue increíblemente útil para mi comprensión del proceso de traducción en Magento. Muchas, muchas gracias, esto definitivamente responde a todas las preguntas que tenía sobre cómo __()funciona la función.
waffl
Una buena descripción de la arquitectura de traducción de Magento también se puede encontrar aquí: gist.github.com/antonmakarenko/7538216
thdoan
@Vinai, excelente respuesta. Realmente me ayudó a resolver un problema de traducción. Publiqué una pregunta aquí . Sorprendentemente, Mage_Tax estaba en conflicto con las traducciones de mi tema, lo que parece contrario a cómo Magento debe dar prioridad a las traducciones
Holly
14

Fuentes de traducción

Las traducciones se fusionan de diferentes fuentes: traducciones de módulos de los archivos XML respectivos, traducciones de translate.csvtemas del tema actual y traducciones en línea de la base de datos.

Las traducciones pueden ser estrictamente específicas del módulo (solo válidas dentro de un módulo), ese es siempre el caso para las traducciones en línea y opcionalmente para las traducciones de temas. Para lograr esto, debe definirlos con el prefijo del módulo en el translate.csv:

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

Las traducciones de módulos (como Mage_Catalog.csv) solo son estrictamente específicas del módulo, si el MODO DESARROLLADOR está activado. De lo contrario, la traducción del primer módulo cargado se usa globalmente para todos los módulos que no tienen su propia traducción para el texto.

Reuní un diagrama de flujo que muestra cómo cada texto de las diferentes fuentes se fusiona en la matriz de traducción:

Fusión de traducción data es la matriz de traducción

Evil Edge Case

Si la cadena traducida es igual a la cadena no traducida, la traducción se ignora. A primera vista, parece una optimización útil, pero de esta manera no se puede traducir fácilmente una cadena sin cambios en un módulo y modificada en otro módulo, porque la traducción modificada será la única y se volverá global.

Búsqueda de traducción

Para qué módulo se busca la traducción, depende del módulo de la clase, en el que __()se ha llamado al método . Entonces, la búsqueda en la matriz de traducción es la siguiente:

Búsqueda de traducción data es la matriz de traducción

Definicion del alcance

Hay posibilidades de cambiar el módulo para una clase, lo cual es especialmente útil para bloques y ayudantes. La mejor práctica es establecer siempre el nombre del módulo explícitamente al reescribir una clase principal. Cómo funciona, varía entre Helpers, Blocks y Contollers (a partir de Magento CE 1.9.1)

Ejemplo para un bloque:

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

Para los bloques, también puede establecer el module_nameparámetro en el diseño XML:

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

Ejemplo para un ayudante:

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

Para los controladores frontend, puede establecer la propiedad _realModuleName, para los controladores de administrador _usedModuleName(sí , por coherencia)

Otros métodos de traducción

En los archivos XML (config.xml, system.xml, layout) puede especificar si los nodos deben traducirse con el translateatributo. También debe agregar el moduleatributo para especificar el alcance, pero aquí el valor debe ser el alias auxiliar , no el nombre del módulo como se indicó anteriormente.

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

En JavaScript puede usar el Translatorobjeto que está disponible globalmente:

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

pero debe hacer que las traducciones que desea utilizar en JavaScript estén disponibles para el objeto traductor. Esto se hace a través de jstranslator.xmlarchivos en los etcdirectorios de módulos.

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

loadingpuede ser cualquier cadena pero debe ser globalmente único. Los atributos translatey modulese utilizan como en otros archivos XML. El valor de messagey su traducción se agrega al objeto JS Translator.

Solución de problemas

Incluso si conoce todas las reglas complicadas, a veces es difícil ver por qué algunas traducciones funcionan como están (o no). Para facilitar esto, desarrollé un módulo de "Sugerencias de traducción" que muestra de dónde provienen las traducciones:

Consíguelo aquí: https://github.com/schmengler/TranslationHints

Captura de pantalla: Sugerencias de traducción


Según las publicaciones y diapositivas de mi blog sobre el tema:

Fabian Schmengler
fuente
2
Espero no enviar correo no deseado al mencionar que mi módulo gratuito Yireo EmailOverride permitirá que los archivos de módulos CSV personalizados también se coloquen en el tema. No solo translate.csv.
Jisse Reitsma
6

¿Has borrado tu caché?

¿Está su sistema configurado en la configuración regional del archivo que está probando?

¿Puede Magento encontrar el archivo que está buscando cuando carga la traducción del tema (algunos temporales var_dump; salir; las declaraciones deberían ayudar.

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

¿Puede el _getTranslatedStringmétodo encontrar lo que está buscando en la matriz de datos?

#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;
}
Alan Storm
fuente
Ninguno de los cachés está activo, no estoy seguro de si mi sistema está configurado en la configuración regional, pero las traducciones funcionan en ciertos archivos de plantilla en consecuencia (al cambiar la tienda). Por ejemplo, una cadena en mi se translate.csvtraduce correctamente /app/design/frontend/package_name/default/template/catalog/product/view.phtmlpero no en/app/design/frontend/package_name/default/template/page/html/topmenu.phtml
waffl
Tenías razón, alguien encendió el caché sin avisarme. ¡Vaya, disculpas y gracias por la información!
waffl
3
@waffl No es necesario disculparse, creo que todos los desarrolladores de Magento lo hacen al menos una vez por semana.
Alan Storm