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

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

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

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

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

25
задан alexteg 10 May 2010 в 22:28
поделиться

3 ответа

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

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 предназначен для использования таким образом. Кроме того, если вам нужно добавлять комментарии к каждому тексту, который вы хотите отобразить, вы a) вероятно, допустите ошибку в какой-то момент, b) весь ваш скрипт будет заполнен текстами в любом случае, только в форме комментариев, c) комментарии должны быть размещены непосредственно над функцией Gettext, что не всегда удобно, в зависимости от положения функции в вашем коде.

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


Другой вариант: объединить 2-й и 3-й варианты:

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

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

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

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

Advantages:

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

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

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

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

26
ответ дан 28 November 2019 в 21:11
поделиться

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

gettext key is 'hello'

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

3
ответ дан 28 November 2019 в 21:11
поделиться

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

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

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

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

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

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

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

13
ответ дан 28 November 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: