Господа! Предлагаю попробовать пообсуждать серьезные вещи

Организация мультиязыковости большого сайта. Допустим мы имеем большой сайт с сотней php (можно и других языков, не важно) страниц-скриптов. Все это крутится-взаимодействует с помощью include в нужном месте, ООП и проч. Задача – организовать текстовые переменные так, чтобы пользователь мог выбирать удобный ему язык (языков не обязательно 2-3, может быть 10-30). По мере поддержки сайта какой-либо язык может добавляться, необходимо учитывать это.

Решения.


Вариант I. Простейший, самый ресурсоемкий. Легок во внедрении, но неудобный в использовании со все более увеличивающимся объемом данных.
Имеем файлы вида «lang_1.inc», “lang_2.inc”, “lang_3.inc” и т.п. В начале скрипта система (например при помощи куков) определяет какой язык нам необходим и подключает необходимый нам файл. А каждый из этих файлов содержит одинаковый набор переменных (т.е. ВСЕ СЛОВА сайта), но с различным значением. Объясню на примере. Пускай у нас русский (lang_1) и английский (lang_2). Имеем два файла со следующим содержанием:

lang_1.inc :
$word_Sun=”Солнце”;
$word_Up=”встало”;

lang_2.inc :
$word_Sun=”The Sun”;
$word_Up=”has got up”;

Система сама подключит необходимый нам файл и, используя команду

print “

”.$word_Sun.” “.$word_Up.”</p>”.”\n”;

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

Преимущества: простая реализация, понятная любому программеру проекта.
Недостатки: ресурсоемкость – придется в каждом скритпе тягать за собой файл с тысячей переменных, хотя необходимо может две-три. Неудобство с ООП. Т.к. в php коряво реализованы классы, то придется в каждом методе класса прописывать что-то вроде

global $word_Sun; global $word_Up;

т.е. каждую использованную переменную нужно еще и объявлять. В результате, если я хочу добавить одно словечко в какой-нибудь свой класс, я должен выдумать имя переменной вроде $word_some, указать его там, где я хотел вставить новое слово, затем в верхушке метода класса прописать global $word_some, а еще зайти в lang_1.inc, lang_2.inc и там добавить значение переменной. На практике – утомляет.


Вариант II. С использованием БД. «Программерский»
Делаем примерно то же самое, только теперь имеем не файлы, а единую таблицу в нашей БД примерно следующего вида:

[id] [name] [lang_1] [lang_2] … [lang_n]

В каждой строчке такой таблицы содержится имя текстового «объекта» и его значения во всех необходимых языках. Пишем простую функцию GetLangValue($name), которая будет возвращать нам необходимое значение по заданному имени. В нашем примере:

print “

”.GetLangValue(“Sun”).” “.getLangValue(“Up”).”</p>”.”\n”;

Преимущества: не нужно нигде указывать никаких global, работаем с БД, достаточно знать имя-синоним нашего «слова». Заполнять базу так же можно только на одном языке, остальные поля оставляя пустыми, глюков не будет, но зато потом видно будет, что заполнено, а что нет, легко добавить значения.
Недостатки: частое обращение к БД. Частые простые выборки для таблицы в 1000 строк. При глюках движка БД теряем даже простую html-страницу. Пользователь просто ничего не увидит. При загрузке БД более приоритетными действиями, бэкапами и прочим – заметное торможение отображения простейших страниц с Hello Word.


Вариант III. Гибридный. «Извращенно-программерский».
Расширяем нашу таблицу полем, которое будет содержать имя (условное) страницы (скрипта), где данная текстовая переменная будет использоваться. Т.к. некоторые переменные (простые слова) будут использоваться во многих таблицах, то можно создать отдельную таблицу где просто будет связка имен страниц с id таблицы переменных. Пример:

[id] [name] [lang_1] [lang_2] [page]
1 Sun Sun Солнце sunlight.php
2 Up up встало sunlight.php
3 Pedro Pedro Педро mexica.php
4 Maria Maria Мария mexica.php

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

sunlight_lang_1.inc :
$word_Sun=”Sun”;
$word_Up=”up”;

sunlight_lang_2.inc :
$word_Sun=”Солнце”;
$word_Up=”встало”;

mexica_lang_1.inc :
$word_Pedro=”Pedro”;
$word_Maria=”Maria”;

mexaica_lang_2.inc :
$word_Pedro=”Педро”;
$word_Maria=”Мария”;

Если активно юзаем ООП (как я), то пожалуй правильней будет делить набор переменных не по названию страниц, а по методу класса (т.е. по названию функции). Так чтобы избежать опять десятка этих global, будет сформирован .inc файл для каждой из сотен различных функций разных классов. А в этих функциях единожды будет прописано include «my_class.my_function_lang_».$lang; Такое же имя будет использовано в поле [page] таблицы в БД.

Преимущества: отличный подход к распределению ресурсов. В скрипт включаются только те переменные, которые необходимы. На php ни единого лишнего действия. Легко расширять данные, один раз прописал в своей функции переменную $word_some, добавил строку в БД с name=some и page=имени функции и работай дальше.
Недостатки: появление огромного количества мелких скриптов. Можно конечно их хранить в отдельной папке, но все же. Сложность с изменением или удалением имени функции, т.к. изменил имя функции или класса, будь добр, поменяй в таблице БД все записи с этим именем, удали старые мелкие скрипты, запусти программу генерации. Сложность перехода, если например уже имеется большая web-система, реализованная по Варианту I. Для нормальной работы необходимо делать отдельный инструмент на php, который будем помогать автоматизировать это.


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

P.S. кстати, существует еще ряд моментов, например, контекстность. Вот имеем две переменных: $word_Sun, $word_Light. На английском Light Sun звучит, на русском Яркий Солнце – не очень. Делать для каждой фразы $word_Sun_Light тоже накладно..