Подтвердить что ты не робот

Перевод более длинных текстов (шаблоны просмотра и электронной почты) с помощью gettext

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Недостатки этого рабочего процесса:

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

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

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

Ответ 2

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

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

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

или

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

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

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

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

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

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

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

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

Чтобы контент выглядел хорошо, иногда вам нужно структурировать свой HTML по-разному. Рассмотрите область кампании с 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

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

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

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

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

Я по-прежнему не продаюсь ни по одному из подходов.