Программирование многоязычных PHP-приложений - PullRequest
13 голосов
/ 16 января 2009

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

Я владею PHP, но никогда не разрабатывал ничего с поддержкой других языков.

Я думал поместить язык в файл PHP с константами, пример:

en.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);

Это хороший способ сделать это?

- Морристор.

Ответы [ 10 ]

11 голосов
/ 17 января 2009

Weird. Люди, кажется, игнорируют очевидное решение. Ваша идея файлов для конкретной локали в порядке. Иметь en.php:

define('LOGIN_INCORRECT','Your login details are incorrect.');
...

Затем, предполагая, что у вас есть глобальный файл конфигурации / констант (который я бы предложил по многим причинам), получите такой код:

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) { ... }
}

фактически абсолютно законны. Используйте их.

8 голосов
/ 16 января 2009

Вы можете использовать gettext или что-то, что поддерживает gettext, а также другие, такие как Zend_Translate .

Edit:

Просто для точности Zend_Translate поддерживает gettext без модуля gettext. Вы можете увидеть здесь много разных типов ввода, которые он поддерживает .

Если вы используете массивы в соответствии с предложением, вы также можете использовать это с Zend_Translate. Дело в том, что если вы сегодня используете массивы и завтра получите gettext, xml или что-то еще, вам нужно только изменить конфигурацию для Zend_Translate.

3 голосов
/ 26 марта 2009

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

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

О том, что их нельзя переопределить; в общем, если вы определяете константы, это потому, что они не нужны или не должны изменяться, поэтому при необходимости вы можете использовать раздел для определенных и переменных строк.

Хочу добавить, что мне не нравится, как выглядят эти файлы, но примите во внимание, что ваши посетители совсем не беспокоятся о том, как реализована идиома, это идеальные правильные реализации, и вы легко можете получить некоторые из них. Traductions.

3 голосов
/ 19 января 2009

Мне очень нравится следующий подход:

один файл - сам переводчик:

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, его даже можно легко кэшировать с помощью кода операции.

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

У меня есть это решение для продуктивного использования с 2004 года, и я очень доволен этим.

Конечно, вы можете даже расширить его соглашениями для множественного числа, например. Локализация числовых форматов - это то, что вам нужно сделать, используя другие средства - на ум приходит расширение intl.

2 голосов
/ 16 января 2009

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

Надежным подходом к обеспечению устойчивости вашего приложения будет использование Zend_Locale в сочетании с Zend_Translate.

Zend_Locale позволяет легко определить языковой стандарт пользователя или установить его, если хотите. Этот класс полезен для автоматической установки правильного формата валюты , например.

Zend_Translate позволяет легко переводить текст с использованием нескольких различных форматов :

  • Массив
  • CSV
  • Gettext
  • Ini
  • TBX
  • Ттй
  • Qt
  • XLIFF
  • XmlTm
2 голосов
/ 16 января 2009

Возможно, вы захотите взглянуть на такую ​​среду, как CakePHP или CodeIgniter, которая значительно упрощает написание интернационализированных приложений. Нужно учитывать не только строки - такие вещи, как числовые форматы и форматы дат, также должны учитываться

0 голосов
/ 16 августа 2012

Вы можете использовать мой любимый язык PHP Многоязычный класс - 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);
0 голосов
/ 18 января 2009

Вот как я это делаю:

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];

}

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

0 голосов
/ 16 января 2009

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

0 голосов
/ 16 января 2009

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

Вы также можете пропустить постоянную часть и просто определить большую хеш-таблицу с переводом константы =>, чтобы предотвратить сбои в пространстве имен.

файл: en.php

$constants = Array(
 'CONSTANT_KEY' => 'Translated string'
);

файл: functions.php

function getConstant($key, $fallback) {
   // ... return constant or fallback here.
}

Однако, когда речь идет о большом количестве данных, этот подход будет сложно поддерживать. Есть несколько других подходов, которые могут лучше служить вашим целям, например, идеальное решение - это когда все ваши константы хранятся в глобальном пространстве памяти для всего вашего сайта, чтобы избежать того, чтобы все запросы / потоки хранили все эти переведенные данные объем памяти. Это требует своего рода модульного подхода php. Gettext, как кто-то здесь предложил, может использовать этот подход.

Google для PHP локализации, чтобы найти полезные ресурсы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...