Юи:Многоязычный веб-сайт – лучшие практики
-
21-09-2019 - |
Вопрос
Я считаю Yii отличным фреймворком, и пример веб-сайта, созданного с помощью оболочки yiic, является хорошей отправной точкой...однако, к сожалению, он не охватывает тему многоязычных веб-сайтов.В документации рассматривается тема перевода коротких сообщений, но не сохранения многоязычного контента...
Я собираюсь начать работу над веб-сайтом, который должен быть как минимум на двух языках, и мне интересно, как лучше всего хранить для него контент...Проблема в том, что контент сильно перемешан с обычными элементами (например, встроенными видеофайлами).
Мне нужно избегать дублирования этих общих ресурсов...до сих пор у меня был массив массивов, содержащих тексты (обычно не более 1-2 коротких абзацев), тогда файл представления просто отображал текст из массива.
Теперь я бы хотел избежать хранения его в массивах (что требует некоторого внимания при заключении двойных кавычек " " и в целом неудобно...).
Итак, как лучше всего сохранить эти короткие абзацы?Должен ли я хранить их в БД, например (id | msg_id | язык | контент), а затем выбирать их по msg_id и языку?Для этого мне все равно нужно создать несколько msg_id и встроить их в файл представления...
Есть ли какая-либо рекомендуемая парадигма, для которой у Yii есть решения?
Спасибо, м.
Решение
Приложение Yii по умолчанию использует метод yii::t() для перевода текстовых сообщений, и существует 3 различных типа источников сообщений:
- CPhpMessageSource :Переводы хранятся в виде пар ключ-значение в массиве PHP.
- CGettextMessageSource :Переводы хранятся в виде файлов GNU Gettext.(PO-файлы)
- CDbMessageSource :Переводы сообщений хранятся в таблицах базы данных.
Если я не ошибаюсь, вы используете классические массивы для переводов.Я рекомендую вам использовать файлы GetText и PO с Yii для операций перевода.
Вы можете найти много информации о переводе и i18n с yii в этом официальная страница документации.
Другие советы
Gettext хорош своей простотой перевода, но реализация PHP по умолчанию не является потокобезопасной.Поэтому Yii использует собственный распаковщик, что значительно увеличивает время обработки по сравнению с массивами PHP.
Поскольку я настраивал сайт с большим объемом транзакций, снижение производительности было неприемлемым.Кроме того, используя APC, мы могли кэшировать перевод PHP, что еще больше повысило производительность.
Поэтому мой подход состоял в том, чтобы использовать массивы PHP, но хранить переводы в БД для удобства перевода, генерируя необходимые файлы при изменении переводов.
БД похожа на эту:
TABLE Message // stores source language, updated by script
id INT UNSIGNED
category VARCHAR(20) // first argument to Yii::t()
key TEXT // second argument to Yii::t()
occurences TINYINT UNSIGNED // number of times found in sources
TABLE MessageTranslation // stores target language, translated by human
id INT UNSIGNED
language VARCHAR(3) // ISO 639-1 or 639-3, as used by Yii
messageId INT UNSIGNED // foreign key on Message table
value TEXT
version VARCHAR(15)
creationTime TIMESTAMP DEFAULT NOW()
lastModifiedTime TIMESTAMP DEFAULT NULL
lastModifiedUserId INT UNSIGNED
Затем я изменил команду yiic 'message' инструмента CLI, чтобы сбрасывать собранные строки в БД.
http://www.yiiframework.com/wiki/41/how-to-extend-yiic-shell-commands/
Оказавшись в базе данных, можно настроить простую CMS, чтобы предоставить переводчикам простой способ перевода и в то же время предоставлять информацию о версиях, возврат к более старым версиям, проверку качества переводчиков и т. д.
Другой скрипт, также модифицированный на основе yiic, затем берет информацию из БД и компилирует ее в массивы PHP.По сути, СОЕДИНЕНИЕ двух таблиц для каждого языка, а затем создание массива с использованием «Message». «key» и «MessageTranslation». «value» в качестве (чего еще?) ключа => значения...сохранение в файл с именем «Сообщение». «Категория» в папке, указанной языком.
Сгенерированные файлы загружаются Yii CPhpMessageSource как обычно.
Для изображений это было так же просто, как поместить их в папки с соответствующим языком и получить язык приложения при связывании.
<img src="/images/<?php echo Yii::app()->language; ?>/help_button.png">
Обратите внимание, что в реальной жизни я написал небольшой вспомогательный метод, позволяющий исключить страну из языковой строки: «en_us» должно быть «en».
Ну, я думаю, что здесь речь идет о том, как переводить статический текст/сообщения на странице, и Yii довольно хорошо решает эту проблему с помощью Yii:t(), и Edigu отвечает за это.
Я просматриваю пост на FlexicaCMS о переводе динамического контента в базе данных, ну, в конечном итоге, это будет следующим после того, как вы решите проблему со статическим текстом/сообщением, и это действительно хороший подход с использованием поведения Yii.Не уверен, что авторы FlexicaCMS слишком амбициозны в поддержке перевода таким образом, поскольку это сделает перевод контента без проблем - действительно здорово.
Единственное, что они не упоминают, — это URL-адрес переведенной страницы.Например, your.site.com/fr/translated_article_title.html.Я имею в виду, что URL-адрес должен содержать часть /language_id/, чтобы он мог помочь с SEO.
В Yii1 и Yii2 yii\i18n\GettextMessageSource в любом случае не использует идеальный механизм кэширования Yii (посмотрите исходный код) для увеличения загрузки файлов PO или MO.Не рекомендуется загружать эти файлы с использованием чистого кода PHP (включая yii\i18n\GettextMessageSource) (это медленнее, чем idx массива php):http://mel.melaxis.com/devblog/2006/04/10/benchmarking-php-localization-is-gettext-fast-enough/
Однако php gettext ext для файлов MO работает немного быстрее, чем перевод php-массива, поскольку он использует кеш, но отрицательным моментом является:каждое изменение в МО требует перезапуска сервера.
Я думаю, что лучшим решением было бы расширить yii\i18n\GettextMessageSource в вашей собственной библиотеке кода и добавить возможность кэширования GettextMessageSource, чтобы повысить его производительность, и использовать вашу расширенную версию в качестве компонента.
protected function loadMessages($category, $language);
Просто не проверяйте дату изменения MO при каждой загрузке для сравнения с кешем, вместо этого очищайте кеш при изменении файлов MO или PO (это может быть расписание).