Я должен разработать довольно простой php-сайт, поэтому мне не нужна инфраструктура. Но он должен поддерживать несколько языков (EN / FR / CHINESE). Я искал PHP, встроенный в систему, и нашел два способа:
У меня нет опыта работы в i18n без рамки, поэтому любые советы о том, что является самым простым способом поддержки нескольких языков?
В конце мне просто нужна функция, которая ищет перевод в файл (один файл по языку). EQ: trans('hello');
=> en.yaml (yaml или нет, это пример)
hello: "Hello world!"
=> fr.yaml
hello: "Bonjour tout le monde !"
И, если возможно, я предпочитаю реализацию Pure PHP
Хотя ext/gettext
и ext/intl
связаны с i18 (интернационализация), gettext
имеет дело с переводом, в то время как intl
занимается интернационализацией таких вещей, как отображение количества и даты, порядок сортировки и транслитерация. Таким образом, вам действительно понадобится как полное i18-решение. В зависимости от ваших потребностей вы можете придумать решение для домашнего приготовления, основанное на упомянутых выше расширениях или на ваших используемых компонентах, которые предоставляются в некоторых рамках:
Zend_Translate
Zend_Locale
Если вам нужен только перевод, а сайт достаточно прост, возможно, ваше простое решение (чтение файла конфигурации перевода в массив PHP с использованием простой функции для извлечения токена) может быть самым простым.
Самое простое решение, о котором я могу думать, это:
$translation = array( 'Hello world!' => array( 'fr' => 'Bonjour tout le monde!', 'de' => 'Hallo Welt!' ) ); if (!function_exists('gettext')) { function _($token, $lang = null) { global $translation; if ( empty($lang) || !array_key_exists($token, $translation) || !array_key_exists($lang, $translation[$token]) ) { return $token; } else { return $translation[$token][$lang]; } } } echo _('Hello World!');
Я знаю, что это старый вопрос, но я чувствую, что ответы не имеют более практического подхода от начала до конца. Это то, что я сделал, чтобы получить перевод с использованием библиотеки gettext
PHP и Poedit без использования каких-либо дополнительных библиотек PHP на сервере Debian:
gettext
и локали на сервере Я не уверен, как это делается с другими операционными системами, но для Debian вы делаете:
sudo apt-get install gettext sudo dpkg-reconfigure locales
Edit : Я предположил, что Ubuntu будет таким же, как Debian, но, по-видимому, он немного отличается. Инструкции по установке локалей на Ubuntu см. На этой странице .
Убедитесь, что вы выбрали все локали, которые хотите использовать. Затем вы должны увидеть что-то вроде:
Generating locales (this might take a while)... en_US.UTF-8... done es_MX.UTF-8... done fr_FR.UTF-8... done zh_CN.UTF-8... done Generation complete.
Примечание. Убедитесь, что вы выбрали правильные варианты и кодировки символов (скорее всего, UTF-8) для каждого языка. Если вы установите es_MX.UTF-8
и попытаетесь использовать es_ES.UTF-8
или es_MX.ISO-8859-1
это не сработает.
Poedit доступен из репозитория программного обеспечения для большинства операционных систем Linux. Для Debian-based просто выполните:
sudo apt-get install poedit
Для Windows и Mac перейдите по адресу : https://poedit.net/download
Хорошо, теперь вы готовы начать кодирование. Я написал следующую функцию gettext()
для перевода как сингулярных, так и множественных чисел:
function __($text, $plural=null, $number=null) { if (!isset($plural)) { return _($text); } return ngettext($text, $plural, $number); }
Пример использования:
// Singular echo __('Hello world'); // Plural $exp = 3; printf( __( 'Your account will expire in %d day', 'Your account will expire in %d days', $exp ), $exp );
Это будет работать на всех языках, а не только на языках, где множественное число есть где-нибудь, где n != 1
– это языки с несколькими множественными типами.
Вы также можете добавить примечания переводчика следующим образом:
/** NOTE: The name Coconut Hotel is a brand name and shouldn't be translated. */ echo __('Welcome to Coconut Hotel');
в/** NOTE: The name Coconut Hotel is a brand name and shouldn't be translated. */ echo __('Welcome to Coconut Hotel');
Вы можете изменить текст с NOTE
на все, что хотите, но вам придется изменить его в сценарии оболочки ниже. Важно : примечание переводчиков должно быть частью комментария к строке, непосредственно предшествующей функции __()
или она не будет поднята при сканировании файлов PHP для переводимых строк.
// Warning! THIS WILL NOT WORK! /* NOTE: This translator's note will not be picked up because it is not immediately preceding the __() function. */ printf( __( 'Your account will expire in %d day', 'Your account will expire in %d days', $exp ), $exp ); // Warning! THIS WILL NOT WORK!
После того, как вы готовы отправить строки переводчикам, сохраните следующий сценарий оболочки (например, update.sh) в корневом каталоге приложения:
#!/bin/sh find . -iname "*.php" | xargs xgettext --add-comments=NOTE --keyword=__:1,2 --keyword=__ --from-code=UTF-8 -o i18n.pot find . -name '*.po' | xargs -I{} msgmerge -U {} i18n.pot
Чтобы выполнить его, просто выполните:
cd /path/to/script && sh update.sh
Это будет рекурсивно сканировать все файлы PHP в этом каталоге и создать файл i18n.pot
(я назвал его i18n.pot
, но не стесняйтесь называть его как угодно) и обновлять любые существующие файлы .po
которые он находит с новыми строками.
Затем нам нужно создать каталоги, в которых будут храниться все файлы локали, по одному для каждого языкового стандарта. Они должны быть формата ./locale/{locale}/LC_MESSAGES
. Например:
cd /path/to/your/project mkdir -p ./locale/en_US.UTF-8/LC_MESSAGES mkdir -p ./locale/es_MX.UTF-8/LC_MESSAGES # ...etc.
Вам нужно выбрать текстовый домен для использования. Это может быть все, что вы хотите, но сценарий будет искать файл с именем {yourTextDomain}.mo
в папке LC_MESSAGES для этого языка. Добавьте в свой PHP-скрипт следующее:
define('TEXT_DOMAIN', 'yourdomain'); bindtextdomain(TEXT_DOMAIN, __DIR__.'/locale'); textdomain(TEXT_DOMAIN); bind_textdomain_codeset(TEXT_DOMAIN, 'UTF-8');
Затем, чтобы перейти на другой язык, выполните следующие действия:
$lang = 'es_MX.UTF-8'; // Change this to the language you want to use if (setlocale(LC_ALL, $lang) === false) { throw new Exception("Server error: The $lang locale is not installed"); } putenv('LC_ALL='.$lang));
Первоначально вы отправляете файл .pot
сгенерированный сценарием выше, переводчикам. Затем они открывают Poedit и нажимают на File > New from POT/PO file
. Когда они сохраняют его, они должны сохранять его как {yourTextDomain}.po
. {yourTextDomain}
должен быть точно таким же, как текстовый домен, который у вас есть в вашем PHP-скрипте. Когда они сохранят его, он автоматически создаст файл .po
файл .mo
. Оба они должны быть сохранены в каталоге LC_MESSAGES
этого языка, когда они будут переведены.
Теперь, когда вы обновляете строки в своем PHP-файле, просто заново запустите сценарий оболочки и отправьте обновленные файлы .po
переводчикам. Затем они переводят строки, и файлы .po
и .mo
необходимо повторно загрузить.
Вот и все. Это может показаться немного трудным для настройки, но как только вы его запускаете, это очень легко.
Gettext кажется тем, что вам нужно. Существует файл langage (кроме оригинального), и он очень прост в использовании:
echo _('Bonjour, ça va ?');
будет печатать Привет, как дела? на английском.
Есть несколько инструментов с gettext, которые могут сканировать ваш php-файл и искать переводимую строку (на самом деле все строки в _ () или gettext ()). Благодаря этому вам не нужно беспокоиться о разных файлах langage. Вы просто кодируете свой сайт в оригинальном langage, и файл langage будет автоматически создан позже.
Тем не менее gettext – это больше инструменты перевода, тогда как intl действительно является i18n (например, для форматирования чисел)
Хотя вам не нужна фреймворк, вы можете использовать фреймворк. Функции интернационализации в Zend Framework довольно хороши, и вы можете просто использовать эту часть, а не использовать все части (включая MVC)