PHP простой подход перевода - Ваше мнение

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

Что Вы думаете об использовании простой функции перевода как один показанный ниже?

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

class Translator{

    private $translations;

    public function __construct(){
        $this->translations = array(
            'Inbox'  => array(
                'en' => 'Inbox',
                'fr' => 'the french word for this'
            ),
            'Messages' => array(
                'en' => 'Messages',
                'fr' => 'the french word for this'
            )
            //And so on...
        );
    }

    public function translate($word,$lang){
        echo $this->translations[$word][$lang];
    }
}
12
задан Peter Mortensen 29 December 2009 в 13:44
поделиться

7 ответов

Выглядит неплохо. Я видел, как это использовалось много раз.

Я бы все-таки разделил разные строки в одном файле на один язык. По крайней мере, или если файлы становятся большими, по одному файлу на модуль на язык.

Тогда ваш класс перевода может загружать и кэшировать языковые файлы (если вы не полагаетесь на любую другую систему кэширования) каждый раз при использовании нового языка.

Небольшой пример того, что я имею в виду

class Translator {
    private $lang = array();
    private function findString($str,$lang) {
        if (array_key_exists($str, $this->lang[$lang])) {
            return $this->lang[$lang][$str];
        }
        return $str;
    }
    private function splitStrings($str) {
        return explode('=',trim($str));
    }
    public function __($str,$lang) {
        if (!array_key_exists($lang, $this->lang)) {
            if (file_exists($lang.'.txt')) {
                $strings = array_map(array($this,'splitStrings'),file($lang.'.txt'));
                foreach ($strings as $k => $v) {
                    $this->lang[$lang][$v[0]] = $v[1];
                }
                return $this->findString($str, $lang);
            }
            else {
                return $str;
            }
        }
        else {
            return $this->findString($str, $lang);
        }
    }
}

Это будет искать .txt файлы, названные в честь языка, в котором есть записи типа this

Foo=FOO
. Bar=BAR

Он всегда отступает назад к строке оригинала, если не находит перевода.

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

Чтобы использовать его гораздо проще, вы всегда можете сделать это и создать файл с именем 'EN_Example.txt'

class Example extends Translator {
    private $lang = 'EN';
    private $package = 'Example';
    public function __($str) {
        return parent::__($str, $this->lang . '_' . $this->package);
    }
}

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

// Translate string "Fox=FOX %s %s"
$e = new Example();
// Translated string with substituted arguments
$s = printf($e->__('Fox'),'arg 1','arg 2');

Для дальнейшей интеграции подстановки переменных функциональность printf можно поместить внутри функции __(), подобной этой

public function __() {
    if (func_num_args() < 1) {
        return false;
    }
    $args = func_get_args();
    $str = array_shift($args);
    if (count($args)) {
        return vsprintf(parent::__($str, $this->lang . '_' . $this->package),$args);
    }
    else {
        return parent::__($str, $this->lang . '_' . $this->package);
    }
}
17
ответ дан 2 December 2019 в 05:03
поделиться

Является ли использование констант (определяет) плохой практикой?

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

У меня есть один portuguese файл и английские файлы, наполненные:

define('CONST','Meaning');

Может быть, это небольшой перебор памяти, но я могу получить доступ из любого места :)

Я могу изменить подход к oop, но пока что у меня есть это.

.
1
ответ дан 2 December 2019 в 05:03
поделиться

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

.
2
ответ дан 2 December 2019 в 05:03
поделиться

Когда у меня была такая проблема (но для очень маленького сайта, всего несколько страниц) давным-давно, я создал файл с именем langpack.php, и любую строку текста на моем сайте нужно было прогнать через него. Теперь я бы использовал аналогичный подход, но разделены на несколько файлов.

Пример подхода ООП

langpack.php

abstract class langpack {
    public static $language = array();

    public static function get($n) {
        return isset(self::$language[$n]) ? self::$language[$n] : null;
    }
}

english.php

final class English extends langpack {
    public static $language = array(
        'inbox' => 'Inbox',
        'messages' => 'Messages',
        'downloadError' => 'There was an error downloading your files',
    );
}

french.php

final class French extends langpack {
    public static $language = array(
        'inbox' => 'Inbioux',
        'messages' => 'Omelette du Fromage',
        'downloadError' => 'C\'est la vie',
    );
}

Вы должны получить идею оттуда. Реализуйте autoloader в конфигурационном файле и тогда загрузка языка должна быть чем-то, что вы можете легко сделать из сессии, URL или чего угодно, используя переменную природу PHP в сочетании с инстанцированием классов, что-то вроде этого:

$langpack = new $_SESSION['language'];
echo $langpack::get('inbox');

Конечно, все это можно сделать с помощью простых массивов, и доступ к ним в обязательном стиле (с абсолютными ссылками, обрабатываемыми через $GLOBALS), чтобы уменьшить некоторые накладные расходы и, возможно, даже сделать механизмы, с помощью которых все это обрабатывается, немного более прозрачными, но, эй, это было бы не очень OOO, не так ли?

1
ответ дан 2 December 2019 в 05:03
поделиться

Есть несколько вещей, о которых Вы, кажется, не задумывались:

  • Вы просто переводите отдельные слова? Как насчет структуры предложения и синтаксиса, который отличается между языками?
  • Что делать, если слово или предложение еще не переведено на язык?
  • Поддерживают ли ваши переводы переменные? Порядок слов в предложении может отличаться в разных языках, и если у Вас есть переменная, то, как правило, ее недостаточно просто разделить вокруг предложения.

Есть два решения, которые я использовал и рекомендовал бы для PHP:

  • gettext - хорошо поддерживается на нескольких языках
  • intsmarty - на основе шаблонов Smarty
4
ответ дан 2 December 2019 в 05:03
поделиться

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

Если у вас много строк, то для загрузки языковых массивов при загрузке всех страниц может потребоваться время, память и жесткие ресурсы. Тогда вы, вероятно, захотите разделить его на разные файлы, или, может быть, даже использовать бэкэнд базы данных. Если Вы используете базу данных i, подумайте об использовании кэширования (например, memcached), чтобы Вам не нужно было опрашивать базу данных сотни раз при каждой загрузке страницы.

Вы также можете посмотреть gettext, который использует прекомпилированные языковые файлы, которые действительно быстрые.

.
2
ответ дан 2 December 2019 в 05:03
поделиться

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

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

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

.
2
ответ дан 2 December 2019 в 05:03
поделиться
Другие вопросы по тегам:

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