Я разрабатываю PHP-приложение, и мне интересно, как лучше всего использовать многоязычную поддержку для пользователей в других странах.
Я владею PHP, но никогда не разрабатывал ничего с поддержкой других языков.
Я думал о том, чтобы поместить язык в файл PHP с константами, например:
ru.php может содержать:
define('HZ_DB_CONN_ERR', 'There was an error connecting to the database.');
и fr.php может содержать:
define('HZ_DB_CONN_ERR', 'whatever the french is for the above...');
Затем я мог бы вызвать функцию и автоматически передать правильный язык.
hz_die('HZ_DB_CONN_ERR', $this);
Это хороший способ обойти это?
– morristhebear.
Weird. Люди, похоже, игнорируют очевидное решение. Ваша идея локальных файлов отлично. Имейте en.php:
define('LOGIN_INCORRECT','Your login details are incorrect.'); ...
Затем, предположив, что у вас есть глобальный файл config / констант (который я бы предложил по многим причинам), введите такой код:
if ($language == 'en') { reqire_once 'en.php'; } else if ($language == 'de') { require_once 'de.php'; }
Вы можете определить функции для отображения числа и валюты, сравнения / сортировки (т.е. у немецкого, французского и английского языков все разные методы сопоставления) и т. Д.
Люди часто забывают, что PHP – это динамический язык, поэтому такие вещи:
if ($language == 'en') { function cmp($a, $b) { ... } } else if ($language == 'de') { function cmp($a, $b) { ... } }
на самом деле совершенно законны. Используй их.
Вы можете использовать gettext или что-то, что поддерживает gettext, а также больше, например Zend_Translate .
Редактировать:
Для точности Zend_Translate поддерживает gettext без модуля gettext. Здесь вы можете увидеть множество различных типов ввода, которые он поддерживает .
Если вы используете массивы, а также предложите использовать это с Zend_Translate. Дело в том, что если вы используете сегодня массивы и gettext, xml или что-то еще, вам нужно изменить свой конфиг для Zend_Translate.
Мне очень нравится следующий подход:
один файл – сам переводчик:
class Translator{ private static $strs = array(); private static $currlang = 'en'; public static function loadTranslation($lang, $strs){ if (empty(self::$strs[$lang])) self::$strs[$lang] = array(); self::$strs[$lang] = array_merge(self::$strs[$lang], $strs); } public static function setDefaultLang($lang){ self::$currlang = $lang; } public static function translate($key, $lang=""){ if ($lang == "") $lang = self::$currlang; $str = self::$strs[$lang][$key]; if (empty($str)){ $str = "$lang.$key"; } return $str; } public static function freeUnused(){ foreach(self::$strs as $lang => $data){ if ($lang != self::$currlang){ $lstr = self::$strs[$lang]['langname']; self::$strs[$lang] = array(); self::$strs[$lang]['langname'] = $lstr; } } } public static function getLangList(){ $list = array(); foreach(self::$strs as $lang => $data){ $h['name'] = $lang; $h['desc'] = self::$strs[$lang]['langname']; $h['current'] = $lang == self::$currlang; $list[] = $h; } return $list; } public static function &getAllStrings($lang){ return self::$strs[$lang]; } } function generateTemplateStrings($arr){ $trans = array(); foreach($arr as $totrans){ $trans[$totrans] = Translator::translate($totrans); } return $trans; }
языковые файлы могут быть просто include()
d и выглядеть следующим образом:
В файле En.php:
Translator::loadTranslation('en', array( 'textfield_1' => 'This is some Textfield', 'another_textfield ' => 'This is a longer Text showing how this is used', ));
de.php:
Translator::loadTranslation('de', array( 'textfield_1' => 'Dies ist ein Textfeld', 'another_textfield ' => 'Dies ist ein längerer Text, welcher aufzeigt, wie das hier funktioniert.', ));
в вашем приложении вы можете либо перевести одну строку следующим образом:
$string = Translator::translate('textfield_1')
или даже пучок строк:
$strings = generateTemplateStrings(array('textfield_1', 'another_textfield'));
Поскольку языковые файлы можно просто включить, вы можете легко складывать и, скажем, включать глобальный файл, а затем включать файлы из подмодулей, которые могут либо добавлять новые строки, либо заменять уже определенные (что не работает с define()
-метод).
Поскольку он является чистым PHP, он может быть даже очень легко кэширован с помощью команды opcode.
У меня даже есть сценарии, вокруг которых генерируются CSV-файлы, содержащие непереведенные строки из файла, и еще лучше: конвертируйте переведенный CSV-файл обратно в файл языка.
У меня есть это решение в продуктивном использовании с 2004 года, и я так доволен этим.
Конечно, вы можете даже расширить его с помощью соглашений для плюрализации, например. Локализация форматов чисел – это то, что вам нужно будет сделать, используя другие средства, – на ум приходит intl-extension.
Спасибо всем людям за ваши подходы и решения. Я пришел сюда с таким же сомнительным вопросом, и я могу заключить, что использовать «метод определения» более реалистично, так как даже с нечетной проблемой, которая не использует очень стильные методы с другими библиотеками или некоторыми, будучи реалистичной и в продуктивном мышлении, настолько прост в использовании, и понимаете, что вы можете получить другие языки через не программирующих навыков.
Я считаю лучше, что метод массивов, так как вам не нужно распространять этот большой мультиязык, чтобы получить некоторые трайкеры, кроме того, вы используете меньше памяти, поскольку вы загружаете только нужные троянные строки.
О том, что это невозможно переопределить; ну, в общем случае, если вы определяете константы, это потому, что они не нужны или не должны быть изменены, поэтому при необходимости вы можете использовать раздел для определенных строк и переменных.
Я добавлю, что мне не нравится, как выглядят эти файлы, но считайте, что ваши посетители не беспокоятся о том, как идиома реализована, – это идеальные правильные реализации, и вы сможете легко получить некоторые трайдерации.
Возможно, вам захочется взглянуть на структуру, такую как CakePHP или CodeIgniter, которые значительно упрощают запись интернационализированных приложений. Это не просто строки, которые вы должны учитывать – такие вещи, как числовые форматы и форматы дат, также должны учитываться
Ваше решение должно работать нормально, если оно предназначено исключительно для перевода. Как отмечали другие, существует множество других переменных на основе языка, таких как форматы валюты и даты.
Zend_Locale
подход к тому, чтобы сделать ваше приложение локальным доказательством, было бы использование Zend_Locale
сочетании с Zend_Translate
.
Zend_Locale
позволяет легко определить локаль пользователя или установить его, если хотите. Этот класс полезен, например, для автоматической настройки правильного формата валюты .
Zend_Translate
позволяет легко переводить текст, используя несколько разных форматов :
Ваш подход работоспособен, в том случае, если вы включаете различные постоянные файлы в зависимости от того, какой язык выбран пользователем.
Вы также можете пропустить константную часть и просто определить большую хэш-таблицу с константой => перевод, чтобы предотвратить сбои в пространстве имен.
файл: en.php
$ constants = Array ( 'CONSTANT_KEY' => 'Переведенная строка' );
файл: functions.php
функция getConstant ($ key, $ fallback) { // ... возвращаем константу или отступаем здесь. }
Однако, когда дело доходит до большого объема данных, этот подход будет трудно поддерживать. Существует несколько других подходов, которые могли бы лучше служить вашей цели, например, идеальным решением является то, где все ваши константы хранятся в глобальном пространстве памяти для всего вашего сайта, чтобы избежать того, чтобы каждый регест или поток сохраняли все эти переведенные данные в Память. Для этого требуется некоторый подход php-модуля. Gettext, как предложил кто-то, может использовать этот подход.
Google для локализации PHP, чтобы найти полезные ресурсы.
Один совет для вас – создать функцию, которая возвращает переведенную строку, и если она не находится в хеш-таблице, верните хеш-ключ, который вы запросили, с чем-то вроде * за ним, чтобы уведомить вас о необходимости перевода.
Вот как я это делаю:
parent_script.php:
$lang_pick = "EN"; //use your own method to set language choice require_once('trans_index.php'); echo $txt['hello'];
trans_index.php:
$text = array(); $text['hello'] = array ( "EN"=> "Hello", "FR"=> "Bonjour", "DE"=> "Guten Tag", "IT"=> "Ciao" ); //as many as needed foreach($text as $key => $val) { $txt[$key] = $text[$key][$lang_pick]; }
Это может быть слишком просто для ваших нужд, но я считаю это очень работоспособным. Это также упрощает поддержку нескольких версий текста.
Вы можете использовать мой любимый язык PHP Multi Language Class – LangQuery
Это самый простой из всех, что я когда-либо видел.
Вы можете сохранить свои языковые данные в .ini-файлы, чем просто называть их
include("LangQuery.php"); $L=new LangQuery(); // Write Hello World echo($L('hello_world')); // Write Hello World Easier - In-line Echo Feature // You don't have to write echo. Just add '>' $L('>hello_world'); // Use in Strings echo("Hello Universe. {$L('hello_world')} Hello Europe"); // Write my age with parameter $L(">my_age",25); // Write my name and age with parameters $L(">my_name_age","Recep",25);
вinclude("LangQuery.php"); $L=new LangQuery(); // Write Hello World echo($L('hello_world')); // Write Hello World Easier - In-line Echo Feature // You don't have to write echo. Just add '>' $L('>hello_world'); // Use in Strings echo("Hello Universe. {$L('hello_world')} Hello Europe"); // Write my age with parameter $L(">my_age",25); // Write my name and age with parameters $L(">my_name_age","Recep",25);