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

Самый эффективный подход для многоязычного веб-сайта PHP

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

  • Gettext функции с генерацией файлов .po
  • Одна таблица MySQL с переводами и уникальный идентификатор строки для каждого текста
  • PHP файлы с массивами, содержащими разные переводы с уникальными идентификаторами строк.

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

Какое наименее ресурсоемкое решение?
Использует ли функции Gettext или файлы PHP с массивами более или менее одинаково требующими ресурсов?
Любые другие предложения для более эффективных решений?

4b9b3361

Ответ 1

Несколько соображений:

1. Переводы
Кто будет делать переводы? Люди, которые также подключены к сайту? Бюро переводов? При использовании Gettext вы будете работать с файлами "pot" (.po). Эти файлы содержат идентификатор сообщения и строку сообщения (перевод). Пример:

msgid "A string to be translated would go here"  
msgstr ""

Теперь это выглядит просто прекрасно и понятно для всех, кому нужно перевести это. Но что происходит, когда вы используете ключевые слова, как предлагает Майк, вместо полных предложений? Если кому-то нужно перевести msgid, называемую "address_home", он или она не имеет понятия, если это должен быть заголовок "Домашний адрес" или что это полное предложение. В этом случае обязательно добавьте комментарии к файлу прямо перед вызовом функции gettext, например:

/// This is a comment that will be included in the pot file for the translators
gettext("ready_for_lost_episode");

Использование xgettext --add-comments=/// при создании файлов .po добавит эти комментарии. Тем не менее, я не думаю, что Gettext может использоваться таким образом. Кроме того, если вам нужно добавить комментарии к каждому тексту, который вы хотите отобразить, вы, возможно, сделаете ошибку в какой-то момент, b) вы целые script будут заполнены текстами в любом случае, только в форме комментариев, c) комментарии должны быть помещены непосредственно над функцией Gettext, что не всегда удобно, в зависимости от положения функции в вашем коде.

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


Другой вариант: объедините свою вторую и третью альтернативу:

Лично я считаю более полезным управлять переводом с помощью (простой) CMS, сохраняя переменные и переводы в базе данных и самостоятельно экспортируя соответствующие тексты в языковые файлы:

  • добавить переменные в базу данных (например: id, page, variable);
  • добавлять переводы к этим переменным (например: id, varId, язык, перевод);
  • выберите соответствующие переменные и переводы, напишите их в файл;
  • включить соответствующий языковой файл на ваш сайт;
  • создайте свою собственную функцию для отображения текста переменных:

text('var'); или, может быть, что-то вроде __('faq','register','lost_password_text');

Точка 3 может быть такой же простой, как выбор всех соответствующих переменных и переводов из базы данных, помещение их в массив и запись serlialized массива в файл.

Преимущества:

  • Обслуживание

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

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

  • Доступ. Это зависит от того, кто будет переводить. Вы можете обернуть CMS простым входом для доступа к людям из агентства переводов, если это необходимо, и только разрешить им изменять определенные языки или даже определенные части сайта. Если это не опция, вы все равно можете выводить данные в файл, который можно вручную перевести и импортировать позже (хотя это может привести к тем же проблемам, что упоминалось ранее). Вы можете добавить один из переводов, которые уже существуют (английский или другой основной язык) в качестве контекста для переводчика.

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

Ответ 2

После некоторого тестирования я, наконец, решил пойти более или менее с линиями комбинации Alecs второй и третьей альтернативы.

Проблема с Gettext
Сначала я попытался настроить всю систему gettext, чтобы попробовать, но оказалось, что это намного сложнее, чем я думал. Проблема в том, что Windows и Unix-системы используют разные языковые сокращения для setlocale(). На данный момент я запускаю свой dev-сервер в Windows с Wamp, а последний сайт будет работать в Linux. После того, как я просмотрел пару дюжина руководства, forums, questions и перезапустить сервер после каждой модификации, Я не мог правильно настроить его каким-либо простым способом. Кроме того, gettext не является потокобезопасным, для обновления языкового файла необходимо перезапустить сервер или взломать, нет простого способа обработки разных версий языковых файлов или обработки исходного текста на английском языке без изменения источника или использования предложения Майка, которое, как указал Алек, не является оптимальным.

Решение
Таким образом, я закончил тем, что, по моему мнению, является лучшим решением, основанным на ответе Алекса:

  • Сохранить все переводы в БД с полями; язык, страница, var_key, версия, версия и last_modified_time - где версия соответствует версиям исходного перевода (на английском языке), а ревизия позволяет переводчику изменять/корректировать завершенные переводы в пределах версии.
  • Используйте CMS для перевода, который связан с БД и обрабатывает разные версии, и позволяет легко просматривать, какие языки переводится, в какой версии и как завершены переводы.
  • При завершении пересмотра версии создаются файлы кеша - каждый файл содержит массив с только var_key и текстовым переводом для одного языка и одной страницы и назван с ISO 639-1 имена языков и имя страницы, такие как: lang/en_index.php Эти языковые файлы затем просто включаются и завернуты в функцию t ($ var_key), что позволяет используя БД во время разработки, а затем изменили, чтобы использовать только файлы кэша.

Производительность
Мне никогда не приходилось проверять gettext, но согласно ссылка, опубликованная Майком, разница в производительности между использованием массива и gettext вполне приемлема для меня за преимущества, которые дает пользовательская система, как описано выше. Тем не менее, я сравнивал использование массива с 20 переведенными текстовыми строками в массиве по сравнению с извлечением тех же 20 текстовых строк из MySQL DB. Оказалось, что использование массива, включенного в файл, было aeound в 6 раз быстрее, чем извлечение всех 20 строк одновременно из базы данных MySQL. Это не было действительно научным эталоном, и результаты, несомненно, могут различаться в разных системах и настройках, но он четко показывает, что я ожидал, - что он будет намного медленнее с использованием БД, чем напрямую с массивом, поэтому я предпочитаю генерировать кеш файлы для массива вместо использования БД.

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

Исходные файлы теста производительности:
PHP: http://pastie.org/964082
Таблица MySQL: http://pastie.org/964115
Это, безусловно, не идеально, но, по крайней мере, создает представление о различиях в производительности.

Ответ 3

Вместо того, чтобы использовать английский текст в качестве ключей, вы могли бы это сделать произвольно, но также предоставлять английские переводы, т.е.

gettext ключ - это "привет"

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