Перевод более длинных текстов (просмотр и шаблоны электронной почты) с помощью gettext - PullRequest
13 голосов
/ 07 ноября 2011

Я разрабатываю многоязычное веб-приложение на PHP, и у меня есть длинные (-ish) тексты, которые мне нужно перевести с помощью gettext. Это шаблоны электронной почты (обычно короткие, но все же несколько строк) и части шаблонов представления (более длинные описательные блоки текста). Эти тексты будут включать в себя несколько простых HTML (например, выделение жирным шрифтом / курсивом, вероятно, ссылка здесь или там). Шаблоны - это PHP-скрипты, вывод которых фиксируется.

Проблема в том, что gettext кажется очень неуклюжим для обработки длинных текстов. Более длинные тексты, как правило, будут иметь больше изменений со временем, чем короткие тексты - я могу либо изменить msgid и обязательно обновить его во всех переводах (это может быть много работы и очень подвержено ошибкам, когда msgid длинный), либо я могу сохранить msgid неизменен и изменяет только переводы (что могло бы ввести в заблуждение устаревшие тексты в шаблонах). Кроме того, я видел совет против включения HTML в строки gettext, но избегая его, можно было бы разбить один естественный фрагмент текста на множество кусков, что будет еще большим кошмаром для перевода и повторной сборки, и я также видел совет против ненужное разбиение строк gettext на отдельные msgids.

Другой подход, который я вижу, состоит в том, чтобы вообще игнорировать gettext для этих более длинных текстов, а также отделять эти блоки во внешних подшаблонах для каждой локали и просто включать один для текущей локали. Недостатком является то, что я разделяю усилия по переводу между файлами getpoxt .po и отдельными шаблонами, расположенными в совершенно другом месте.

Поскольку это приложение будет использоваться в качестве отправной точки для других приложений в будущем, я пытаюсь найти наилучший подход в долгосрочной перспективе. Мне нужен совет для лучших практик в таких сценариях. Как вы реализовали подобные случаи? Что получилось, а что оказалось плохой идеей?

Ответы [ 3 ]

10 голосов
/ 16 ноября 2011

Вот рабочий процесс, который я использовал на очень загруженном сайте, на котором было около нескольких десятков длинных блоков стилизованного текстового контента, переведенных на шесть языков:

  1. Выберите текстовый язык разметки (мы использовали Markdown )
  2. Для длинных строк используйте фиксированные идентификаторы сообщений, такие как "About_page_intro_markdown", которые:
    • описывает смысл текста
    • поясняет, что он будет интерпретирован в формате уценки
  3. Сделайте так, чтобы наше приложение отображало строки "* _markdown" надлежащим образом, позволяя использовать только несколько безопасных HTML-тегов
  4. Создать инструмент для переводчиков, который:
    • показывает им, что их Markdown отображается в реальном времени (вроде как Markdown dingus )
    • облегчает им просмотр теперь авторитетного базового языка перевода текста (так как его больше нет в msgid)
  5. Научите переводчиков использовать новый рабочий процесс

Плюсы этого рабочего процесса:

  • Идентификаторы сообщений не меняются постоянно
  • Поскольку переводчики редактируют в безопасном высокоуровневом синтаксисе, HTML-код трудно испортить
  • Нетехническим переводчикам было очень легко писать в Markdown по сравнению с HTML

Минусы этого рабочего процесса:

  • Наличие статических неизменяемых идентификаторов сообщений означает, что изменения в тексте должны передаваться вне диапазона (что мы будем делать в любом случае, так как длинный текст может вызвать вопросы о тоне или акценте)

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

Надеюсь, это поможет, и удачи в вашем проекте.

5 голосов
/ 20 февраля 2014

У меня только что была эта конкретная проблема, и я думаю, что я решил ее элегантным способом.

Проблема: мы хотели использовать Gettext в PHP и использовать строки основного языка в качестве перевода ключей. Однако для больших блоков HTML (с h1, h2, p, a и т. Д.) Мне бы пришлось либо:

  • Создать перевод для каждого тега с контентом.

или

  • Поместите весь блок с тегами в один перевод.

Ни один из этих вариантов мне не понравился, поэтому я сделал следующее:

  • Сохраняйте простые строки («OK», «Добавить», «Подтвердить», «My Awesome App») как обычные записи Gettext .po с исходным текстом в качестве ключа
  • Пишите содержимое (большие текстовые блоки) в уценке и сохраняйте их в файлах. Файлы примеров: /homepage/content.md (основной / исходный текст), /homepage/content.da-DK.md, /homepage/content.de-DE.md

  • Напишите класс, который выбирает файлы содержимого (для текущей локали) и анализирует его. Затем я использовал это как:

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

Однако как насчет динамического большого текста? Просто. Используйте шаблонизатор. Я выбрал Smarty и использовал его в своем Template классе.

Теперь я могу использовать логику шаблонов .. в уценке! Как это круто?!

Затем наступила сложная часть ..

Чтобы контент выглядел хорошо, иногда вам нужно структурировать HTML по-другому. Рассмотрим область кампании с 3 «функциональными блоками» под ней. Простое решение: подготовьте файл для области кампании и один файл для каждого из 3 блоков.

Но я мог бы сделать лучше, чем это.

Я написал быстрый синтаксический анализатор блоков, чтобы записывать все содержимое в один файл, а затем отдельно обрабатывать каждый блок.

Файл примера:

[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] ...

И вот как я бы их отобразил в разметке:

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

Боюсь, я не могу предоставить какой-либо исходный код, так как это было для проекта компании, но я надеюсь, что вы поняли.

3 голосов
/ 08 ноября 2011

gettext не был предназначен для перевода больших фрагментов текста.

fwiw Я включил базовый HTML (сильный, a и т. Д.) В строки gettext, так как был уверен, что наши переводчики знают, что они делают (в основном правильно), и что переводы будут хорошо протестированы.

Я пробовал подход разбить текст на одну строку в абзаце. Как ни странно, если в середине текста есть один абзац английского языка. Когда одна из этих строк изменилась, это означало, что нам пришлось ждать переводов, прежде чем выпускать новую версию, что замедлило нас. С другой стороны, переводчикам легко увидеть, какая часть текста изменилась. Этот подход хорошо работал для одного приложения, с которым я пробовал.

Разделение некоторого текста на внешние местоположения также сработало, но это вызвало накладные расходы управления, а не просто файл .po или два, была целая куча другого текста, который нужно было вручную сравнить с английской версией и соответствующим образом обновить. , Это выполнимо, если вы не забыли предоставить примечания своим переводчикам, объясняющие, где и в чем разница в английской версии.

Я все еще не продан ни на одном подходе.

...