2011-11-07 13 views
12

Zajmuję się tworzeniem wielojęzycznej aplikacji internetowej PHP i mam długie (-ish) teksty, które muszę przetłumaczyć za pomocą gettext. Są to szablony wiadomości e-mail (zazwyczaj krótkie, ale wciąż kilka linii) i części szablonów widoku (dłuższe opisowe bloki tekstu). Teksty te zawierają prosty HTML (np. Pogrubienie/kursywa dla podkreślenia, prawdopodobnie link tu lub tam). Szablony to skrypty PHP, których wyniki są przechwytywane.Tłumaczenie dłuższych tekstów (widoków i szablonów wiadomości e-mail) za pomocą gettext

Problem polega na tym, że gettext wydaje się bardzo niezdarny w obsłudze dłuższych tekstów. Dłuższe teksty generalnie będą miały więcej zmian w czasie niż krótkie teksty - mogę zmienić msgid i zaktualizować go we wszystkich tłumaczeniach (może być dużo pracy i bardzo podatny na błędy, gdy msgid jest długi), lub mogę zachować msgid pozostaje niezmieniony i modyfikuje tylko tłumaczenia (które pozostawiałyby mylące nieaktualne teksty w szablonach). Ponadto, widziałem porady przeciwko włączaniu HTML do ciągów gettext, ale unikanie go złamałoby jeden naturalny fragment tekstu na wiele fragmentów, co będzie jeszcze większym koszmarem do przetłumaczenia i ponownego złożenia, a także widziałem porady przeciwko niepotrzebne dzielenie ciągów gettext na osobne msgids.

Innym podejściem, jakie widzę, jest całkowite zignorowanie tekstu gettext dla tych dłuższych tekstów i oddzielenie tych bloków w zewnętrznych podtablicach dla każdego ustawienia narodowego, a także uwzględnienie tego dla bieżącego locale. Wadą jest to, że oddzielam wysiłek tłumaczenia między plikami getpext .po i osobnymi szablonami znajdującymi się w zupełnie innej lokalizacji.

Ponieważ ta aplikacja będzie używana jako punkt wyjścia dla innych aplikacji w przyszłości, staram się zaproponować najlepsze podejście w dłuższej perspektywie. Potrzebuję porady dotyczącej najlepszych praktyk w takich sytuacjach. W jaki sposób wdrożyłeś podobne przypadki? Co się okazało do pracy i co okazało się złym pomysłem?

+1

Powiązane: [Jak skutecznie pracować z plikami PO gettext podczas wprowadzania małych zmian do dużych wartości tekstowych] (http://stackoverflow.com/questions/2966026/), [Łączenie klawiszy i pełnego tekstu podczas pracy z gettext i. pliki po] (http://stackoverflow.com/questions/15743919/), [Czy jest dobrym pomysłem, aby identyfikator wiadomości był tekstem w języku angielskim?] (http://stackoverflow.com/questions/216478/), [Czy mogę automatycznie zaktualizować pliki msgids do plików .po w gettext, aby uzyskać proste zmiany tekstu?] (Http://stackoverflow.com/questions/8288050/) – ento

Odpowiedz

9

Oto workflow Kiedyś, w bardzo dużym stopniu odwiedzanych miejscu, które miało około kilkudziesięciu długo-owski bloków stylizowany zawartości tekstowej, przetłumaczony na sześć języków:

  1. wybrać język znaczników tekstowych (użyliśmy Markdown)
  2. w przypadku długich ciągów używać identyfikatorów stałych wiadomości jak „About_page_intro_markdown”, że:
    • opisuje intencje tekstu
    • wyjaśnia, że ​​to będzie interpretować w formacie wyprzedaży
  3. Czy nasza aplikacja render „* _markdown” struny odpowiednio, upewniając się, aby pozwolić tylko kilka bezpiecznych znaczniki HTML
  4. zbudować narzędzie dla tłumaczy, że:
    • pokazuje im Markdown renderowane w czasie rzeczywistym (coś w rodzaju Markdown dingus)
    • ułatwia je zobaczyć teraz-autorytatywny tłumaczenie języka bazowa tekstu (jako że nie jest już w msgid)
  5. Teach tłumaczy w jaki sposób korzystać z nowego workflow

Zalety tego przepływu pracy:

  • identyfikatory wiadomości nie zmieniają się cały czas
  • Ponieważ tłumacze edytujesz w bezpiecznym poziomie wyższym składnia, trudno bałagan HTML znaleźć
  • tłumaczy Nietechniczne to bardzo łatwe do napisania w promocji cenowych, w porównaniu z HTML

minusy tego przepływu pracy:

  • Posiadające statycznych niezmienne identyfikatory komunikat oznacza zmiany w tekście muszą być przesyłane poza pasmem (co chcielibyśmy zrobić tak, jak długo tekst może rodzić pytania o ton lub naciskiem)

Jestem bardzo zadowolony ze sposobu, w jaki ten przepływ pracy działał na naszej stronie internetowej, i zdecydowanie poleciłbym go i użyłbym go ponownie. Rozpoczęło się kilka dni, ale było to łatwe do zbudowania, szkolenia i uruchomienia.

Mam nadzieję, że to pomoże i powodzenia w projekcie.

+0

Twoje podejście jest naprawdę interesujące, ale mam wątpliwości. Czy to podejście jest całkowicie niezależne od gettext lub zamierzone z nim pracować? Jeśli jest przeznaczony do pracy z gettext. Gdzie jest połączenie? Prawdopodobnie czegoś mi brakuje. – lordscales91

+0

@ lordscales91Ten proces workflow może działać dobrze z programem gettext lub innym równoważnym systemem - o ile tworzysz dodatkowe narzędzia opisane w krokach # 3 i # 4. – Anirvan

3

gettext nie został zaprojektowany do tłumaczenia dużych fragmentów tekstu.

fwiw Dołączyłem podstawowy kod HTML (silny, a, itp.) W ciągach gettext, ponieważ byłem przekonany, że nasi tłumacze wiedzieli, co robią (w większości przypadków) i że tłumaczenia będą dobrze przetestowane.

Próbowałem już podejścia do rozbijania tekstu na jeden ciąg na akapit. Z grubsza wygląda to dziwnie, jeśli w środku tekstu jest jeden akapit z angielskiego. Tam, gdzie zmienił się jeden z tych napisów, musieliśmy czekać na tłumaczenie przed wydaniem nowej wersji, co spowolniło nas. Z drugiej strony tłumaczom łatwo jest sprawdzić, która część tekstu się zmieniła. To podejście sprawdza się w przypadku jednej aplikacji, z którą ją wypróbowałem.

Dzielenie niektórych tekstów na lokalizacje zewnętrzne również zadziałało, ale spowodowało to narzut zarządzania, a nie tylko plik .po lub dwa, istniała cała masa innych tekstów, które musiały być ręcznie porównane z wersją angielską i zaktualizowane odpowiednio. Jest to możliwe, jeśli pamiętasz o dostarczaniu notatek do tłumaczy wyjaśniających, gdzie i jaka jest różnica w wersji angielskiej.

Wciąż nie jestem sprzedawany w żadnym z tych sposobów.

5

Po prostu miałem ten szczególny problem i uważam, że rozwiązałem go w elegancki sposób.

Problem: Chcieliśmy użyć Gettext w PHP i użyć podstawowych łańcuchów językowych jako kluczy tłumaczeń. Jednak w przypadku dużych bloków HTML (z h1, h2, p, a, itp.) Muszę albo:

  • Utworzyć tłumaczenie dla każdego tagu z zawartością.

lub

  • Put cały blok z tagami w jednym tłumaczeniu.

Żadna z tych opcji mi do gustu, więc to, co zrobiłem:

  • Przechowywać prostych ciągów ("OK", "Dodaj", "Potwierdź", "Mój Niesamowite App") jako regularne wpisy GetPext .po, z oryginalnym tekstem jako kluczem
  • Zapisuj zawartość (duże bloki tekstu) w przecenach i przechowuj je w plikach. Przykładowe pliki byłoby /homepage/content.md (tekst pierwotny/źródło), /homepage/content.da-DK.md, /homepage/content.de-DE.md

  • Napisz klasy, która pobiera pliki zawartości (dla bieżącej lokalizacji) i analizuje je. I wtedy używane to lubią:

    <?=Template::getContent("homepage/content")?>

Jednak to, co o dynamicznym dużym tekście? Prosty. Użyj silnika szablonowego. Zdecydowałem się na Smarty i użyłem go w mojej klasie Template.

Mogłem teraz używać szablonów logicznych .. w markdown! Jak to jest niesamowite ?!

Potem przyszedł Najtrudniejsze ..

dla treści, aby wyglądać dobrze, czasami trzeba uporządkować kod HTML inaczej. Rozważ obszar kampanii z 3 "pudełkami funkcji" poniżej. To proste rozwiązanie: przygotuj plik dla obszaru kampanii i jeden dla każdy z z 3 pól.

Ale mógłbym zrobić lepiej.

Napisałem szybki parser blokowy, więc napisałbym całą treść w jednym pliku, a następnie wyrenderowałem każdy blok oddzielnie.

Przykład file:

[block campaign] 
Buy this now! 
============= 

Blaaaah... And a smarty tag: {$cool} 
[/block] 

[block feature 1] 
Feature 1 
--------- 

asdasd you get it.. 
[/block] 

[block feature 2] ... 

I to jak bym czyni je w znacznikach:

<?php 
// At the top of the document... 

// Class handles locale. :) 
$template = Template::getContent("homepage/content", [ 
    "cool" => "Smarty variable! AWESOME!" 
]); 
?> 

... 

<title><?=_("My Awesome App")?></title>  

... 

<div class="hero"> 
    <!-- Template data already processed! :) --> 
    <?=$template->renderBlock("campaign")?> 
</div> 
<div class="featurebox"> 
    <?=$template->renderBlock("feature 1")?> 
</div> 
<div class="featurebox"> 
    <?=$template->renderBlock("feature 2")?> 
</div> 

Obawiam się, że nie może dostarczyć żadnego kodu źródłowego, jak to było za projekt firmy, ale mam nadzieję, że wpadniesz na ten pomysł.