Como implementar traduções em CSVs de pacotes de modelos de design? Como echo $ this -> __ ('Text') funciona?

29

Eu tenho uma configuração de pacote de design assim:

design/frontend/package_name/theme_name/locale/

sob o qual eu tenho

de_DE, en_GBetc, nos quais tenho translate.csvarquivos correspondentes com as várias strings:"Key", "Translation"

Eu estou tentando implementar várias seqüências de caracteres no meu tema usando echo $this->__('Text')

No entanto, parece não funcionar (só vejo a string dentro da ('Text')tela exibida). Eu acho que estou perdendo algum entendimento fundamental de quando o Magento extrai strings do CSV para ser traduzido. Alguém pode explicar como fazer com que esses arquivos csv funcionem?

waffl
fonte
Qual versão do Magento você está executando?
philwinkle
Eu estou usando Magento v: 1.7.0.2
waffl
Você está chamando isso fora de um arquivo de modelo normal do magento? Talvez você precise chamar a classe helper e torná-la algo como <? Php echo Mage :: helper ('core') -> __ ('Text'); ?> Também tente habilitação "Traduzir em linha" na Frontend em Sistema> Configuração> Desenvolvedor
SaveTheMage

Respostas:

84

TL; DR

Se você não estiver interessado nos detalhes de como a tradução funciona, pule o conteúdo até a seção
O que verificar se a sua tradução não está funcionando abaixo, especialmente a subseção
Solução para tradução do escopo do módulo .

Visão Geral da Tradução Magento

O Magento prioriza as fontes de tradução (do mais alto para o mais baixo):

  1. DB (a core_translatetabela)
  2. O translate.csvarquivo do tema
  3. Os app/locale/*/*.csvarquivos

Como é construída a matriz de tradução?

Traduções de módulos

Primeiro, todos os arquivos app/locale/*/*.csvmencionados nos etc/config.xmlarquivos dos módulos ativos são analisados. Aqui está uma explicação passo a passo do processo:
Suponha que o Magento encontre a seguinte config.xmlseção:

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

E nesse arquivo, a seguinte tradução é especificada para o código do idioma configurado para a exibição atual da loja:

"AAA","BBB"

Nessas circunstâncias, o Magento cria os seguintes registros na matriz de conversão:

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

O segundo valor é a conversão do escopo do módulo . O nome do módulo prefixado é obtido do nó XML de configuração que contém a declaração do arquivo de conversão.

Se a mesma tradução for especificada novamente por um segundo arquivo de módulo , por exemplo, na Some_Module.csvtradução "AAA","CCC", NÃO SUBSTITUIRÁ a "AAA"configuração. Em vez disso, ele adicionará apenas um novo registro com o segundo nome do módulo "Some_Module::AAA" => "CCC".

Se o modo de desenvolvedor é habilitado, ele mesmo irá resetar o "AAA"registro se ele encontra um segundo disco com a mesma chave em outra tradução módulo. Isso facilita identificar conflitos de conversão de módulos durante o desenvolvimento.

Traduções Temáticas

Segundo, as traduções carregadas do primeiro translate.csvarquivo no fallback de tema para o código do idioma atual simplesmente substituem os registros existentes na matriz de conversão.
Portanto, continuando o exemplo anterior, um translate.csvregistro "AAA","DDD"levaria aos seguintes dados de conversão:

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

É claro que os registros nas translate.csvnovas chaves de conversão são simplesmente adicionados à matriz.

Traduções de banco de dados

As traduções da core_translatetabela são basicamente mescladas na matriz de tradução, assim como as traduções do tema.
As chaves existentes das traduções do módulo ou do tema são substituídas pelos registros do banco de dados, novas são adicionadas.

Pesquisa de tradução

Quando o __()método é chamado, o Magento primeiro procura uma tradução em array que corresponda ao módulo atual.
O módulo atual é determinado pelo nome da classe em que a __()classe é chamada. Por exemplo, em blocos, o método responsável se parece com isso:

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

Os métodos em auxiliares e controladores funcionam de maneira correspondente.

Cenários de pesquisa de exemplo

Por exemplo, digamos que $this->__('AAA')seja chamado em um arquivo de modelo. Se o bloco associado tiver o tipo Mage_Core_Block_Template, o Magento primeiro procurará um Mage_Core::AAAregistro. Se não o encontrar, retornará à tradução da chave AAA.
No cenário de exemplo, isso resultará na tradução DDD(do translate.csvarquivo).

Em um cenário diferente, o bloco associado poderia estar Mage_Catalog_Block_Product_View. Nesse caso, o Magento primeiro procuraria um registro de tradução Mage_Catalog::AAAe encontraria a tradução AAA.

Portanto, as traduções do escopo do módulo têm uma prioridade mais alta que as traduções genéricas . Qual tradução é usada depende de qual módulo a classe está chamando o __()método.

O que verificar se sua tradução não está funcionando

Se sua tradução de um translate.csvarquivo não estiver sendo usada, siga esta lista de verificação:

  1. O cache de tradução está desativado / atualizado? (Solução: limpe o cache)
  2. O translate.csvarquivo está realmente no fallback de tema da loja atual? (Solução: corrija a configuração do tema)
  3. Existe um registro conflitante para a tradução na core_translatetabela? (Solução: remova o registro conflitante de core_translate)
  4. Se todos os pontos anteriores não forem a causa, deve haver uma tradução conflitante de um módulo diferente. (Solução: veja abaixo)

Solução para conflitos de conversão de escopo de módulo

Se você achar que o caso final é verdadeiro, basta adicionar a tradução uma segunda vez ao seu translate.csv com o escopo do módulo que está fazendo a tradução.
No exemplo, se você sempre quis AAAser traduzido como DDDatravés da tradução do tema, você pode fazer isso no seu translate.csv:

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

Na prática, apenas adiciono o escopo do módulo à tradução se houver um conflito, ou seja, se uma tradução não estiver funcionando.

Notas Adicionais

Tradução Inline

O recurso de tradução em linha do Magento também adiciona as traduções personalizadas à core_translatetabela usando o prefixo do escopo do módulo.

Compatibilidade com versões anteriores

A prioridade das traduções do tema costumava ser maior que as traduções do banco de dados até o Magento versão 1.3 ou mais.

Tradução XML

Magento, por vezes, avaliar translate=""argumentos config.xml, system.xmle XML disposição para traduzir valores nó filho.
Uma classe auxiliar pode ser especificada nesses casos usando o module=""argumento para especificar o módulo para o escopo da conversão.
Se nenhum moduleargumento for especificado no XML, o core/dataauxiliar será usado para converter os valores do nó filho.

Outras informações

Confesso que encobri alguns detalhes do processo de tradução do Magento neste post, mas apenas porque não quero muita informação.

  • Alguns detalhes técnicos enquanto a matriz de tradução é criada
  • A possibilidade de usar arquivos de tradução adicionais para módulos
  • Escopo da visualização da loja para core_translateregistros
  • Prós e contras usando os diferentes métodos de tradução

Faça uma pergunta separada, se mais informações forem necessárias.

Vinai
fonte
1
OK, sinto muitíssimo todo mundo, mas alguém ativou os caches sem me dizer ... Provavelmente no momento em que comecei a trabalhar nas traduções. Suspiro. Esta informação foi incrivelmente útil para minha compreensão do processo de tradução no Magento. Muito obrigado, isso definitivamente responde a todas as perguntas que eu tinha sobre como a __()função funciona.
waffl
Uma visão muito boa da arquitetura tradução do Magento também pode ser encontrada aqui: gist.github.com/antonmakarenko/7538216
thdoan
@Vinai, excelente resposta. Isso realmente me ajudou a resolver um problema de tradução que eu postei aqui . Surpreendentemente Mage_Tax foi em conflito com as traduções de meu tema que parece contrário à forma como Magento é destinado traduções priorizar a
Holly
14

Fontes de tradução

As traduções são mescladas de diferentes fontes: traduções de módulo dos respectivos arquivos XML, traduções de temas do translate.csvtema atual e traduções embutidas do banco de dados.

As traduções podem ser estritamente específicas do módulo (válidas apenas dentro de um módulo), esse é sempre o caso das traduções inline e, opcionalmente, das traduções dos temas. Para conseguir isso, você deve defini-los com o prefixo do módulo no translate.csv:

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

As traduções dos módulos (como Mage_Catalog.csv) são estritamente específicas do módulo, se o DEVELOPER MODE estiver ativado. Caso contrário, a tradução do primeiro módulo carregado é usada globalmente para todos os módulos que não têm sua própria tradução para o texto.

Eu montei um fluxograma que mostra como cada texto de diferentes fontes é mesclado na matriz de tradução:

Mesclagem de tradução data é a matriz de tradução

Evil Edge Case

Se a sequência traduzida for igual à sequência não traduzida, a tradução será ignorada. Parece uma otimização útil à primeira vista, mas dessa maneira você não pode traduzir facilmente uma string inalterada em um módulo e alterada em outro módulo, porque a tradução alterada será a única e se tornará global.

Pesquisa de tradução

Para qual módulo a tradução é procurada, depende do módulo da classe, no qual o método __()foi chamado. Em seguida, a pesquisa na matriz de conversão é a seguinte:

Pesquisa de tradução data é a matriz de tradução

Definição de escopo

Existem possibilidades de alterar o módulo para uma classe, o que é especialmente útil para blocos e auxiliares. A melhor prática é sempre definir o nome do módulo explicitamente ao reescrever uma classe principal. Como funciona, varia entre auxiliares, blocos e controladores (a partir do Magento CE 1.9.1)

Exemplo para um bloco:

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

Para blocos, você também pode definir o module_nameparâmetro no XML do layout:

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

Exemplo para um ajudante:

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

Para controladores de front-end, você pode definir a propriedade _realModuleName, para controladores de administrador, _usedModuleName(yay por consistência)

Outros métodos de tradução

Nos arquivos XML (config.xml, system.xml, layout), você pode especificar se os nós devem ser traduzidos com o translateatributo Você também deve adicionar o moduleatributo para especificar o escopo, mas aqui o valor deve ser o alias auxiliar , não o nome do módulo, como acima.

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

Em JavaScript, você pode usar o Translatorobjeto que está disponível globalmente:

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

mas você precisa disponibilizar as traduções que deseja usar em JavaScript para o objeto tradutor. Isso é feito através de jstranslator.xmlarquivos nos etcdiretórios dos módulos.

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

loadingpode ser qualquer string, mas deve ser globalmente exclusivo. Os atributos translatee modulesão usados ​​como em outros arquivos XML. O valor de messagee sua conversão são adicionados ao objeto JS Translator.

Solução de problemas

Mesmo que você conheça todas as regras complicadas, às vezes é difícil perceber por que algumas traduções estão funcionando como estão (ou não). Para facilitar, desenvolvi um módulo "Translation Hints", que mostra de onde vêm as traduções:

Obtenha aqui: https://github.com/schmengler/TranslationHints

Captura de tela: Dicas de tradução


Com base nos meus posts e slides sobre o tópico:

Fabian Schmengler
fonte
2
Espero não estar enviando spam ao mencionar que meu módulo gratuito Yireo EmailOverride também permitirá que arquivos personalizados do módulo CSV sejam colocados no tema. Não apenas translate.csv.
Jisse Reitsma 11/09/15
6

Você limpou seu cache?

Seu sistema está definido para o código do idioma do arquivo que você está testando?

O Magento pode encontrar o arquivo que está procurando quando carrega a tradução do tema (algumas var_dumpinstruções temporárias ; exit; exit devem ajudar.

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

O _getTranslatedStringmétodo pode encontrar o que está procurando na matriz de dados?

#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
fonte
Nenhum dos caches está ativo, não tenho certeza se meu sistema está definido como localidade, mas as traduções funcionam em determinados arquivos de modelo de acordo (alterando a loja). Por exemplo, uma corda em meus translate.csvtraduz adequadamente em /app/design/frontend/package_name/default/template/catalog/product/view.phtml, mas não em/app/design/frontend/package_name/default/template/page/html/topmenu.phtml
waffl
Você estava certo, alguém ligou o cache sem me dizer. Opa, minhas desculpas e obrigado pela informação!
waffl
3
@ waffl Não precisa se desculpar - acho que todo desenvolvedor do Magento faz isso pelo menos uma vez por semana.
Alan Storm