Jak wdrożyć tłumaczenia w CSV pakietu szablonu projektu? Jak działa echo $ this -> __ ('Text')?

29

Mam taką konfigurację pakietu projektowego:

design/frontend/package_name/theme_name/locale/

pod którą mam

de_DE, en_GBEtc, w ramach której mają odpowiednie translate.csvpliki z różnych ciągów:"Key", "Translation"

Próbuję zaimplementować różne ciągi w moim motywie echo $this->__('Text')

Jednak wydaje się, że to nie działa (widzę tylko ciąg wewnątrz ('Text')wyświetlanego). Myślę, że brakuje mi pewnego podstawowego zrozumienia, kiedy Magento pobiera ciągi z pliku CSV do przetłumaczenia. Czy ktoś może wyjaśnić, jak uruchomić te pliki csv?

gofr
źródło
Jaką wersję Magento używasz?
philwinkle,
Korzystam z Magento v: 1.7.0.2
waffl 13.08.13
Czy nazywasz to poza zwykłym plikiem szablonu Magento? Być może musisz wywołać klasę pomocnika i zrobić z niej coś w rodzaju <? Php echo Mage :: helper ('core') -> __ ('Text'); ?> Spróbuj także
włączyć opcję

Odpowiedzi:

84

TL; DR

Jeśli nie jesteś zainteresowany szczegółami, w jaki sposób działa tłumaczenie, pomiń treść do sekcji
Co sprawdzić, czy tłumaczenie nie działa poniżej, szczególnie podsekcja
Rozwiązanie konfliktów w zakresie zakresu modułów .

Przegląd tłumaczeń Magento

Magento nadaje priorytet źródłom tłumaczeń (od najwyższego do najniższego):

  1. DB ( core_translatetabela)
  2. Tematem translate.csvplik
  3. te app/locale/*/*.csvpliki

Jak zbudowana jest tablica tłumaczeń?

Tłumaczenia modułów

Najpierw parsowane są wszystkie pliki, do app/locale/*/*.csvktórych istnieją odniesienia z etc/config.xmlplików aktywnych modułów . Oto przewodnik po tym procesie:
Załóżmy, że Magento znajduje następującą config.xmlsekcję:

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

W tym pliku podano następujące tłumaczenie dla ustawień regionalnych skonfigurowanych dla bieżącego widoku sklepu:

"AAA","BBB"

W tych okolicznościach Magento tworzy w tablicy tłumaczeń następujące rekordy:

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

Druga wartość to tłumaczenie zakresu modułu . Prefiksowana nazwa modułu jest pobierana z węzła config XML zawierającego deklarację pliku tłumaczenia.

Jeśli to samo tłumaczenie jest określone ponownie przez drugiego pliku modułu , np Some_Module.csvtłumaczenie jest "AAA","CCC", to będzie Nie zastępuj na "AAA"ustawienie. Zamiast tego doda tylko nowy rekord z nazwą drugiego modułu "Some_Module::AAA" => "CCC".

Jeśli włączony jest tryb dewelopera, to nawet rozbroić ten "AAA"rekord, jeżeli stwierdzi drugi rekord z tym samym kluczem w innym tłumaczeniu modułu. Ułatwia to wykrywanie konfliktów translacji modułów podczas programowania.

Tłumaczenia tematyczne

Po drugie, tłumaczenia wczytane z pierwszego translate.csvpliku w zastępczej kompozycji dla bieżących ustawień regionalnych po prostu zastępują istniejące rekordy w tablicy tłumaczeń.
Kontynuując poprzedni przykład, translate.csvzapis "AAA","DDD"prowadziłby do następujących danych tłumaczenia:

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

Oczywiście rekordy translate.csvz nowymi kluczami do tłumaczenia są po prostu dodawane do tablicy.

Tłumaczenia bazy danych

Tłumaczenia z core_translatetabeli są w zasadzie łączone w tablicę tłumaczeń, podobnie jak tłumaczenia motywów.
Istniejące klucze z tłumaczenia modułu lub motywu są nadpisywane przez rekordy bazy danych, dodawane są nowe.

Wyszukiwanie tłumaczeń

Po __()wywołaniu metody Magento najpierw szuka tłumaczenia w tablicy pasującego do bieżącego modułu.
Bieżący moduł jest określony przez nazwę klasy, na której __()klasa jest wywoływana. Na przykład w blokach odpowiedzialna metoda wygląda następująco:

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

Metody w Pomocnikach i Kontrolerach działają odpowiednio.

Przykładowe scenariusze wyszukiwania

Na przykład, powiedzmy, że $this->__('AAA')jest wywoływany w pliku szablonu. Jeśli skojarzony blok ma typ Mage_Core_Block_Template, Magento najpierw sprawdzi Mage_Core::AAArekord. Jeśli go nie znajdzie, wróci do tłumaczenia klucza AAA.
W przykładowym scenariuszu spowoduje to tłumaczenie DDD(z translate.csvpliku).

W innym scenariuszu skojarzonym blokiem może być Mage_Catalog_Block_Product_View. W takim przypadku Magento najpierw sprawdzi rekord tłumaczenia Mage_Catalog::AAAi znajdzie tłumaczenie AAA.

W efekcie tłumaczenia zakresu modułów mają wyższy priorytet niż wszelkie tłumaczenia ogólne . To, które tłumaczenie zostanie zastosowane, zależy od tego, który moduł klasy wywołuje __()metodę.

Co sprawdzić, jeśli tłumaczenie nie działa

Jeśli tłumaczenie z translate.csvpliku nie jest używane, postępuj zgodnie z poniższą listą kontrolną:

  1. Czy pamięć podręczna tłumaczenia jest wyłączona / odświeżona? (Rozwiązanie: wyczyść pamięć podręczną)
  2. Czy translate.csvplik naprawdę zawiera kreację zastępczą dla bieżącego sklepu? (Rozwiązanie: napraw konfigurację motywu)
  3. Czy w core_translatetabeli występuje sprzeczny zapis tłumaczenia ? (Rozwiązanie: usuń sprzeczny rekord z core_translate)
  4. Jeśli wszystkie poprzednie punkty nie są przyczyną, musi istnieć sprzeczne tłumaczenie z innego modułu. (Rozwiązanie: patrz poniżej)

Rozwiązanie konfliktów translacji zakresu modułów

Jeśli okaże się ostateczna przypadek jest prawdziwy, wystarczy dodać tłumaczeniu po raz drugi do Twojego translate.csv z zakresu modułu modułu robi tłumaczenia.
W tym przykładzie, jeśli zawsze chciałeś AAAbyć tłumaczony za DDDpomocą tłumaczenia motywu, możesz to zrobić w translate.csv:

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

W praktyce dodam zakres modułu do tłumaczenia tylko wtedy, gdy występuje konflikt, to znaczy, jeśli tłumaczenie nie działa.

Dodatkowe uwagi

Tłumaczenie Inline

Funkcja tłumaczenia wbudowanego Magento dodaje również niestandardowe tłumaczenia do core_translatetabeli przy użyciu prefiksu zakresu modułu.

Kompatybilność wsteczna

Priorytet tłumaczeń motywów był wyższy niż tłumaczenia baz danych aż do wersji Magento 1.3.

Tłumaczenie XML

Magento czasami ocenić translate=""argumenty config.xml, system.xmli układ XML do przeliczenia wartości węzłów potomnych.
W takich przypadkach można określić klasę pomocnika, używając module=""argumentu do określenia modułu dla zakresu tłumaczenia.
Jeśli modulew pliku XML nie podano żadnego argumentu, core/datapomocnik służy do tłumaczenia wartości węzłów potomnych.

Dalsza informacja

Przyznaję, że w tym poście opisałem kilka szczegółów procesu tłumaczenia Magento, ale tylko dlatego, że nie chcę za dużo informacji.

  • Niektóre szczegóły techniczne podczas budowania tablicy translacji
  • Możliwość użycia dodatkowych plików tłumaczeń dla modułów
  • Przechowuj zakres widoku dla core_translaterekordów
  • Plusy i minusy za pomocą różnych metod tłumaczenia

Jeśli potrzebujesz więcej informacji, zadaj osobne pytanie.

Vinai
źródło
1
OK, niewiarygodnie przepraszam wszystkich, ale ktoś inny włączył pamięci podręczne, nie mówiąc mi ... Prawdopodobnie w chwili, gdy zacząłem pracować nad tłumaczeniami. Westchnienie. Ta informacja była jednak niezwykle pomocna dla mojego zrozumienia procesu tłumaczenia w Magento. Wielkie dzięki, to zdecydowanie odpowiada na wszystkie pytania, które miałem na temat działania tej __()funkcji.
waffl
Całkiem dobry przegląd architektury tłumaczeń Magento można również znaleźć tutaj: gist.github.com/antonmakarenko/7538216
thdoan
@Vinai, doskonała odpowiedź. Naprawdę pomogło mi to rozwiązać problem z tłumaczeniem, na który tutaj zadałem pytanie . Co zaskakujące, Mage_Tax był w konflikcie z tłumaczeniami mojego motywu, co wydaje się sprzeczne z tym, w jaki sposób Magento ma priorytetowo traktować tłumaczenia
Holly,
14

Źródła tłumaczeń

Tłumaczenia są łączone z różnych źródeł: tłumaczenia modułów z odpowiednich plików XML, tłumaczenia motywów z translate.csvbieżącego motywu i tłumaczenia wbudowane z bazy danych.

Tłumaczenia mogą być ściśle specyficzne dla modułu (ważne tylko w module), zawsze tak jest w przypadku tłumaczeń wbudowanych i opcjonalnie w przypadku tłumaczeń motywów. Aby to osiągnąć, musisz zdefiniować je z prefiksem modułu w translate.csv:

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

Tłumaczenia z modułów (podobnych Mage_Catalog.csv) są ściśle specyficzne dla modułu, tylko jeśli włączony jest TRYB DEWELOPERA. W przeciwnym razie tłumaczenie z pierwszego załadowanego modułu jest używane globalnie dla wszystkich modułów, które nie mają własnego tłumaczenia tekstu.

Przygotowałem schemat blokowy, który pokazuje, jak każdy tekst z różnych źródeł jest scalany w tablicy tłumaczeń:

Scalanie tłumaczeń data to tablica tłumaczeń

Skrzynia Evil Edge

Jeśli przetłumaczony ciąg jest równy nieprzetłumaczonemu ciągowi, tłumaczenie jest ignorowane. Na pierwszy rzut oka to brzmi jak przydatna optymalizacja, ale w ten sposób nie można łatwo przetłumaczyć łańcucha bez zmian w jednym module i zmienionym w innym module, ponieważ zmienione tłumaczenie będzie jedynym i stanie się globalne.

Wyszukiwanie tłumaczeń

Dla którego modułu wyszukiwane jest tłumaczenie, zależy od modułu klasy, na której __()została wywołana metoda . Następnie wyszukiwanie w tablicy tłumaczeń wygląda następująco:

Wyszukiwanie tłumaczeń data to tablica tłumaczeń

Definicji zakresu

Istnieje możliwość zmiany modułu dla jednej klasy, co jest szczególnie przydatne dla bloków i pomocników. Najlepszą praktyką jest zawsze jawne ustawianie nazwy modułu podczas przepisywania klasy podstawowej. Jak to działa, różni się w zależności od pomocników, bloków i kontrolerów (od Magento CE 1.9.1)

Przykład bloku:

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

W przypadku bloków można również ustawić module_nameparametr w układzie XML:

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

Przykład dla pomocnika:

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

W przypadku kontrolerów interfejsu użytkownika można ustawić właściwość _realModuleName, w przypadku kontrolerów administracyjnych _usedModuleName(dla zachowania spójności)

Inne metody tłumaczenia

W plikach XML (config.xml, system.xml, layout) możesz określić, czy węzły powinny być tłumaczone za pomocą tego translateatrybutu. Należy również dodać moduleatrybut, aby określić zakres, ale tutaj wartością musi być alias pomocnika , a nie nazwa modułu, jak wyżej.

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

W JavaScript możesz użyć Translatorobiektu, który jest globalnie dostępny:

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

ale musisz udostępnić tłumaczenia, których chcesz używać w JavaScript, dla obiektu translatora. Odbywa się to poprzez jstranslator.xmlpliki w etckatalogach modułów.

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

loadingmoże być dowolnym ciągiem, ale musi być globalnie unikalny. translateI moduleatrybuty są wykorzystywane także w innych plikach XML. Wartość messagei jej tłumaczenie jest dodawane do obiektu JS Translator.

Rozwiązywanie problemów

Nawet jeśli znasz wszystkie skomplikowane reguły, czasem trudno jest zrozumieć, dlaczego niektóre tłumaczenia działają tak, jak działają (lub nie działają). Aby to ułatwić, opracowałem moduł „Wskazówki dotyczące tłumaczenia”, który pokazuje, skąd pochodzą tłumaczenia:

Pobierz tutaj: https://github.com/schmengler/TranslationHints

Zrzut ekranu: Wskazówki dotyczące tłumaczenia


Na podstawie moich postów na blogu i slajdów na ten temat:

Fabian Schmengler
źródło
2
Mam nadzieję, że nie spamuję, mówiąc, że mój bezpłatny moduł Yireo EmailOverride zezwoli również na umieszczanie niestandardowych plików modułu CSV w motywie. Nie tylko translate.csv.
Jisse Reitsma,
6

Czy wyczyściłeś pamięć podręczną?

Czy w Twoim systemie ustawiono ustawienia regionalne testowanego pliku?

Czy Magento może znaleźć plik, którego szuka, gdy ładuje tłumaczenie motywu (niektóre tymczasowe var_dump; zakończ; instrukcje powinny pomóc.

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

Czy _getTranslatedStringmetoda może znaleźć to, czego szuka w tablicy danych?

#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
źródło
Żadna pamięć podręczna nie jest aktywna, nie jestem pewien, czy mój system jest ustawiony na ustawienia regionalne, ale tłumaczenia działają odpowiednio w niektórych plikach szablonów (zmieniając sklep). Na przykład, ciąg w moim translate.csvtłumaczeniu poprawnie tłumaczy w, /app/design/frontend/package_name/default/template/catalog/product/view.phtmlale nie w/app/design/frontend/package_name/default/template/page/html/topmenu.phtml
waffl
Miałeś rację, ktoś włączył pamięć podręczną, nie mówiąc mi o tym. Ups, przepraszam i dziękuję za informację!
waffl
3
@waffl Nie trzeba przepraszać - myślę, że każdy programista Magento robi to przynajmniej raz w tygodniu.
Alan Storm