Подскажите кто сталкивался с многоязычностью и шаблонизатором smarty, у меня есть в бд в таблицах столбцы с текстом на разных языках, как мне определить язык пользователя, написать функцию обработки языка и выдать пользователю, использую шаблонизатор smarty поэтому код пишу под шаблонизатор.
Ну ты получай язык в обработчике. Смарти должно быть пофигу, что выдавать. Т.е., в шаблоне вывод переменной {{ name }}, а в обработчике получаешь язык, вытаскиваешь нужные данные из бд, а потом передаёшь в шаблонизатор. Т.е. все языковые конструкции решаются на уровне контроллеров\моделей, а в шаблонизатор передаёшь уже готовые данные
ну с реализацией у меня хреново, не столь богат опытом, подскажи как правильно написать обработчик который определяет язык, я с многоязычностью впервые столкнулся.
вот это мне и надо написать какой язык используется, мне нужно для начала определить какой язык используется, задать глобальную переменную $lang потом её уже засовывать в функцию которая будет сравнивать язык в переменной $lang и выводить тот, который нужен с бд. примерно как будет выглядить по моим соображениям(на сколько это правильно ...хз...): Код (Text): $sql = "SELECT * FROM ................"; $rs = mysql_query($sql); while($row = mysql_fetch_assoc($rs)){ if ($lang==$GLOBALS[RUS_LANG]){ $rs=$row[NAME_RUS]; }elseif($lang==$GLOBALS[CN_LANG]){ $rs=$row[NAME_CN]; }elseif($lang==$GLOBALS[ENG_LANG]){ $rs=$row[NAME_ENG]; }else{ $rs=$row[NAME_ENG]; } $smartyRs[] = $rs; } return $smartyRs;
нет --- Добавлено --- ты ранее уже писал обработчики для определения языка? если есть опыт, то поделись) --- Добавлено --- ранее я пробовал использовать gettext, но он переводит с английского на русский, а вот с других языков не переводит, искал решение проблемы, но так и не нашел в чем заключалась проблема. приходится с бд теперь вытягивать инфу на разных языках.
Тут сначала тебе надо определиться, как ты будешь хранить действующий язык. Можно рулить через роутер, можно через сессии, можно ещё как-нибудь. Я, например, в текущем проекте, рулю через роутер. Т.е. в контроллерах у меня роут такого вида: PHP: /** * @Route("/{lang}/category", name="category") */ public function categoryAction(Request $request, $lang) { //controller } в базе данных (или в файлике, тут не важно) хранится список всех возможных языков. Т.е. по ссылке /ru/category у меня в контроллере в переменной $lang находится по этой ссылке строка "ru". В моём случае, конечно, нужно каждый запрос проверять язык. Ну а дальше, используя переменную с языком, брать нужный вариант перевода и уже отправлять в шаблонизатор. Можно сделать сессиями. Т.е. при заходе на сайт установить сессию с нужным языком, и танцевать уже от неё
в старой версии сайта в файле index.php прописывался вот такой код: Код (Text): $lang=$_REQUEST["lang"]; $must=$_REQUEST["must"]; if($folder_id){ }else{ $folder_id=-1; } if($must==1){ }else{ if (preg_match("/ru/i",$_SERVER["HTTP_ACCEPT_LANGUAGE"])) {$lang="NAME_RUS";} if (preg_match("/cn/i",$_SERVER["HTTP_ACCEPT_LANGUAGE"])) {$lang="NAME_ENG";} if (preg_match("/uk/i",$_SERVER["HTTP_ACCEPT_LANGUAGE"])) {$lang="NAME_UKR";} } if($lang=="NAME_ENG"){ }elseif($lang=="NAME_RUS"){ }elseif($lang=="NAME_CN"){ }elseif($lang=="NAME_UKR"){ }else{ $lang="NAME_ENG"; } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" <? if($lang=="NAME_ENG"){ ?> xml:lang="en" lang="en"><? }elseif($lang=="NAME_RUS"){ ?> xml:lang="en" lang="ru"><? }elseif($lang=="NAME_CN"){ ?> xml:lang="en" lang="cn"><? }elseif($lang=="NAME_UKR"){ ?> xml:lang="en" lang="uk"><? }else{ ?> xml:lang="en" lang="en"><? } ?> только я вот хз, можно этот код использовать или лучше перепелить его?
Слушай, я даже не знаю. Лично я не встречался с указанием языка в заголовках. Ну хз, может и я неправ в данной ситуации, но мне как-то предпочтительнее языком рулить через роуты. Как у тебя в целом код работает немного непонятно. Ну, точнее вроде всё как ясно, но непонятно что там за $folder_id, за что она отвечает, почему она касается выбора языка и тд. Но в принципе это к нашему вопросу имеет мало значения. В общем смотри, объясню как бы сделал я без фреймворка. Я бы сделал ссылки такого вида: /ru/controller/action (на контроллер и экшен можешь не смотреть. В принципе нас сейчас интересует только /ru/) т.е. первый блок в ссылке я бы оставил под языковую версию. Потом берём ссылку, парсим её, находим первый элемент (в котором у нас сейчас ru) и танцуем от него. В принципе это работа в несколько строчек. Но тут правда я ещё хз как у тебя вообще роутер работает. Может получиться и так, что контроллеры перестанут цепляться. В общем без твоей архитектуры непонятно. И есть ли у тебя вообще роутер, тоже непонятно. Расскажешь как у тебя там всё работает?
в файле model.php я формирую запросы к бд, прогоняю полученные данные через ассоциативный массив, передаю функцию Код (Text): function indexAction($smarty) { // параметром передаю ему объект smarty $itemId = isset($_GET['id']) ? $_GET['id'] : null; if($itemId == null) exit(); $rsProduct = getProductById($itemId); $smarty->assign('rsProduct', $rsProduct); в контроллер(controller.php), а с него уже отправляю в шаблонизатор ассоц. массив и подставляю в нужные теги необходимые ключи, а он уже соответсвенно меняет их на свойства ключа, выводя весь перечень. --- Добавлено --- на форуме частенько читал про то что делали через кеш, но через роут первый раз слышу.
@AlexsaiL а как у тебя сам роут устроен? Ну т.е. вот есть у тебя ссылка, по которой ты переходишь. Должна открыться определённая страничка, т.е. сработать нужный контроллер. Вот как у тебя происходит такой роут?
Код (Text): function indexAction($smarty) { $catId = isset($_GET['id']) ? $_GET['id'] : null; if($catId == null) exit(); получаю строку из бд данные по текущей категории страницу которую открыл. $rsCategory = getCatById($catId); завожу переменную $rsCategory и присваиваю значение, результатом выполнения функции - getCatById (получить категорию по её индитификатору) и параметром передаю эту функцию индетификатор который к нам пришел параметром _GET .
Ну можешь также и передать тогда. Только странно это, рулить контроллерами через гет-параметры. Хз, я бы переписал всё)
ну если я бы знал как можно сделать лучше) я бы сделал). а как бы сделал ты? --- Добавлено --- а если передать так же через гет- параметры, то как правильнее сформулировать?
если не поленишься, то вот статья про простенький такой роут и вообще паттерн MVC. Чисто по подобию можно сделать. Элегантно, красиво, для начала. После неё поймёшь, что я тут про роуты говорил. https://habrahabr.ru/post/150267/ А если через гет-параметры, то в принципе тоже самое, что я и говорил, только без роута. Из гет-параметра получаешь язык и работаешь с ним. Ну допустим возьмём контроллер (тут я даже твой контроллер возьму): получаем язык из гет-параметра PHP: function indexAction($smarty) { // параметром передаю ему объект smarty $lang = $_GET['lang']; //тут будут манипуляции с языком, чуть дальше опишу $itemId = isset($_GET['id']) ? $_GET['id'] : null; if($itemId == null) exit(); $rsProduct = getProductById($itemId); $smarty->assign('rsProduct', $rsProduct); вот, язык приняли. Допустим, у нас есть таблица в бд, которая содержит имя (ну неважно, это чисто для примера). В этой таблице 3 поля: id, name_ru, name_en. Т.е. у нас два языка. (тут реализовано может быть вообще как угодно. Главное сам принцип) Теперь учитывая язык выберем имя из базы данных, т.е. $name = select * from table; ассоциативный массив и тд и тп, а в шаблонизатор передаём типо так: PHP: $smarty->assign('name', $name['name_' . $lang]); т.е. шаблонизатор в принципе не знает, что есть несколько языков. Он только выводит name. А вот что будет в этом name - решает обработчик --- Добавлено --- PS: это примитивно-хреновая реализация. Я описал вообще приблизительный принцип работы. Так-то надо подумать над этим получше, улучшить и тд
ну в том случае, что мы щас пообсуждали, то нет. Я вообще, если честно, первый раз на практике сталкиваюсь с такими заголовками. Слышать слышал, но в пользовании не видел. Может я херовый прогер, конечно. А так, с этим заголовком происходит всё тоже самое, что я написал выше, только язык берётся не из гета, а из заголовка. Ну и да, заголовок тогда нужно будет отправлять на каждую страницу. Можешь и так сделать, в принципе. Но я бы не заморачивался. А можешь вообще тупо сессию создать и всё. При первом входе записать в сессию стандартный язык (русский, например). Если человек меняет язык - контроллер обрабатывает запрос и пишет в переменную сессионную новый язык. Тогда уже язык брать не из гета, а из сессии. А вообще, сделай сначала через гет. Просто чтобы понять как это будет работать. Переписать потом под сессии или заголовок, да или даже роутер - несложно. Ну, в принципе там переписана будет только строчка с получением и установкой языка.
скажи мне плз, а вот в шаблоне в файле tpl, как вывести тогда вот так: {$item['NAME_' $lang]}? ранее я так выводил: {$item['NAME_RUS']}
@AlexsaiL, не. я думал я описал так, что ты понял. Но походу нет =D смотри. Шаблонизатор не должен знать ничего о языке. вот строка, которая была у тебя PHP: $smarty->assign('rsProduct', $rsProduct); этим ты передаёшь в шаблонизатор переменную rsProduct, в шаблонизаторе она будет иметь значение такое, которое у тебя лежит в контроллере в переменной $rsProduct дальше, смотри PHP: $smarty->assign('name', $name['name_' . $lang]); тут мы передаёт в шаблонизатор переменную name, а значение у неё будет $name['name_' . $lang] т.е. допустим, если подняться к коду выше ($name = select * from table, из базы данных мы получили такой массив: PHP: $name = ["id" => "1", "name_ru" = > "русское имя", "name_en" => "английское имя"]; а в шаблонизатор мы передаём: $name['name_' . $lang] т.е. если у нас $lang = ru, то в шаблонизатор уйдёт $name['name_ru'], если en, то $name['name_en' ]. Но! Шаблонизатор не знает этих переменных, он знает только свою переменную name. А значение этой переменной мы указываем в контроллере этой строчкой PHP: $smarty->assign('name', $name['name_' . $lang]); Вот я к чему. Разруливаем все вопросы, касаемо языка, в обработчиках. А в шаблонизатор только выведет переменную name. А вот что в ней будет храниться - решит в данном случае контроллер