За последние 24 часа нас посетили 22946 программистов и 1264 робота. Сейчас ищут 756 программистов ...

Определение языка пользователя и выдача текста на нужном языке.(для шаблонизатора Smarty)

Тема в разделе "PHP и базы данных", создана пользователем AlexsaiL, 24 апр 2017.

  1. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    Подскажите кто сталкивался с многоязычностью и шаблонизатором smarty, у меня есть в бд в таблицах столбцы с текстом на разных языках, как мне определить язык пользователя, написать функцию обработки языка и выдать пользователю, использую шаблонизатор smarty поэтому код пишу под шаблонизатор.
     
  2. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Ну ты получай язык в обработчике. Смарти должно быть пофигу, что выдавать. Т.е., в шаблоне вывод переменной {{ name }}, а в обработчике получаешь язык, вытаскиваешь нужные данные из бд, а потом передаёшь в шаблонизатор.
    Т.е. все языковые конструкции решаются на уровне контроллеров\моделей, а в шаблонизатор передаёшь уже готовые данные
     
  3. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    ну с реализацией у меня хреново, не столь богат опытом, подскажи как правильно написать обработчик который определяет язык, я с многоязычностью впервые столкнулся.
     
  4. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Ну а как ты определяешь, какой язык используется?
     
  5. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    вот это мне и надо написать какой язык используется, мне нужно для начала определить какой язык используется, задать глобальную переменную $lang потом её уже засовывать в функцию которая будет сравнивать язык в переменной $lang и выводить тот, который нужен с бд. примерно как будет выглядить по моим соображениям(на сколько это правильно ...хз...):
    Код (Text):
    1.  
    2. $sql = "SELECT * FROM ................";
    3. $rs = mysql_query($sql);
    4. while($row = mysql_fetch_assoc($rs)){
    5.                 if ($lang==$GLOBALS[RUS_LANG]){
    6.                     $rs=$row[NAME_RUS];
    7.                 }elseif($lang==$GLOBALS[CN_LANG]){
    8.                     $rs=$row[NAME_CN];
    9.                 }elseif($lang==$GLOBALS[ENG_LANG]){
    10.                     $rs=$row[NAME_ENG];
    11.                 }else{
    12.                     $rs=$row[NAME_ENG];
    13.                 }
    14.                 $smartyRs[] = $rs;
    15.             }
    16.     return $smartyRs;
     
    #5 AlexsaiL, 24 апр 2017
    Последнее редактирование: 24 апр 2017
  6. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    На фреймворке пишешь?
     
  7. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    нет
    --- Добавлено ---
    ты ранее уже писал обработчики для определения языка? если есть опыт, то поделись)
    --- Добавлено ---
    ранее я пробовал использовать gettext, но он переводит с английского на русский, а вот с других языков не переводит, искал решение проблемы, но так и не нашел в чем заключалась проблема. приходится с бд теперь вытягивать инфу на разных языках.
     
  8. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Тут сначала тебе надо определиться, как ты будешь хранить действующий язык. Можно рулить через роутер, можно через сессии, можно ещё как-нибудь.
    Я, например, в текущем проекте, рулю через роутер. Т.е. в контроллерах у меня роут такого вида:
    PHP:
    1. /**
    2.      * @Route("/{lang}/category", name="category")
    3.      */
    4.     public function categoryAction(Request $request, $lang)
    5.     {
    6.         //controller
    7.     }
    в базе данных (или в файлике, тут не важно) хранится список всех возможных языков.
    Т.е. по ссылке /ru/category у меня в контроллере в переменной $lang находится по этой ссылке строка "ru". В моём случае, конечно, нужно каждый запрос проверять язык. Ну а дальше, используя переменную с языком, брать нужный вариант перевода и уже отправлять в шаблонизатор.
    Можно сделать сессиями. Т.е. при заходе на сайт установить сессию с нужным языком, и танцевать уже от неё
     
  9. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    в старой версии сайта в файле index.php прописывался вот такой код:
    Код (Text):
    1. $lang=$_REQUEST["lang"];
    2. $must=$_REQUEST["must"];
    3. if($folder_id){
    4. }else{
    5.     $folder_id=-1;
    6. }
    7. if($must==1){
    8.    
    9. }else{
    10.     if (preg_match("/ru/i",$_SERVER["HTTP_ACCEPT_LANGUAGE"])) {$lang="NAME_RUS";}
    11.     if (preg_match("/cn/i",$_SERVER["HTTP_ACCEPT_LANGUAGE"])) {$lang="NAME_ENG";}
    12.     if (preg_match("/uk/i",$_SERVER["HTTP_ACCEPT_LANGUAGE"])) {$lang="NAME_UKR";}
    13. }
    14.  
    15. if($lang=="NAME_ENG"){
    16. }elseif($lang=="NAME_RUS"){
    17. }elseif($lang=="NAME_CN"){
    18. }elseif($lang=="NAME_UKR"){
    19. }else{
    20.     $lang="NAME_ENG";
    21. }
    22. ?>
    23. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    24. <html xmlns="http://www.w3.org/1999/xhtml"
    25. <?
    26. if($lang=="NAME_ENG"){
    27.     ?> xml:lang="en" lang="en"><?
    28. }elseif($lang=="NAME_RUS"){
    29.     ?> xml:lang="en" lang="ru"><?
    30. }elseif($lang=="NAME_CN"){
    31.     ?> xml:lang="en" lang="cn"><?
    32. }elseif($lang=="NAME_UKR"){
    33.     ?> xml:lang="en" lang="uk"><?
    34. }else{
    35.     ?> xml:lang="en" lang="en"><?
    36. }
    37.  
    38. ?>
    только я вот хз, можно этот код использовать или лучше перепелить его?
     
  10. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Слушай, я даже не знаю. Лично я не встречался с указанием языка в заголовках. Ну хз, может и я неправ в данной ситуации, но мне как-то предпочтительнее языком рулить через роуты.
    Как у тебя в целом код работает немного непонятно. Ну, точнее вроде всё как ясно, но непонятно что там за $folder_id, за что она отвечает, почему она касается выбора языка и тд. Но в принципе это к нашему вопросу имеет мало значения.

    В общем смотри, объясню как бы сделал я без фреймворка.
    Я бы сделал ссылки такого вида:
    /ru/controller/action
    (на контроллер и экшен можешь не смотреть. В принципе нас сейчас интересует только /ru/)
    т.е. первый блок в ссылке я бы оставил под языковую версию.
    Потом берём ссылку, парсим её, находим первый элемент (в котором у нас сейчас ru) и танцуем от него. В принципе это работа в несколько строчек. Но тут правда я ещё хз как у тебя вообще роутер работает. Может получиться и так, что контроллеры перестанут цепляться. В общем без твоей архитектуры непонятно. И есть ли у тебя вообще роутер, тоже непонятно. Расскажешь как у тебя там всё работает?
     
  11. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    в файле model.php я формирую запросы к бд, прогоняю полученные данные через ассоциативный массив, передаю функцию
    Код (Text):
    1. function indexAction($smarty) { // параметром передаю ему объект smarty
    2.       $itemId = isset($_GET['id']) ? $_GET['id'] : null;
    3.       if($itemId == null) exit();
    4. $rsProduct = getProductById($itemId);
    5.  
    6. $smarty->assign('rsProduct', $rsProduct);
    в контроллер(controller.php), а с него уже отправляю в шаблонизатор ассоц. массив и подставляю в нужные теги необходимые ключи, а он уже соответсвенно меняет их на свойства ключа, выводя весь перечень.
    --- Добавлено ---
    на форуме частенько читал про то что делали через кеш, но через роут первый раз слышу.
     
  12. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    @AlexsaiL а как у тебя сам роут устроен? Ну т.е. вот есть у тебя ссылка, по которой ты переходишь. Должна открыться определённая страничка, т.е. сработать нужный контроллер. Вот как у тебя происходит такой роут?
     
  13. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    Код (Text):
    1. function indexAction($smarty) {
    2.     $catId = isset($_GET['id']) ? $_GET['id'] : null;
    3.     if($catId == null) exit();
    получаю строку из бд данные по текущей категории страницу которую открыл.
    $rsCategory = getCatById($catId); завожу переменную $rsCategory и присваиваю значение, результатом выполнения функции - getCatById (получить категорию по её индитификатору) и параметром передаю эту функцию индетификатор который к нам пришел параметром _GET .
     
  14. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    т.е. у тебя все роуты через гет-параметры идут?
     
  15. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    да
    --- Добавлено ---
    думаю может так же передать и выбранные язык?
     
  16. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    Ну можешь также и передать тогда.
    Только странно это, рулить контроллерами через гет-параметры. Хз, я бы переписал всё)
     
  17. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    ну если я бы знал как можно сделать лучше) я бы сделал). а как бы сделал ты?
    --- Добавлено ---
    а если передать так же через гет- параметры, то как правильнее сформулировать?
     
  18. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    если не поленишься, то вот статья про простенький такой роут и вообще паттерн MVC. Чисто по подобию можно сделать. Элегантно, красиво, для начала. После неё поймёшь, что я тут про роуты говорил. https://habrahabr.ru/post/150267/
    А если через гет-параметры, то в принципе тоже самое, что я и говорил, только без роута. Из гет-параметра получаешь язык и работаешь с ним.
    Ну допустим возьмём контроллер (тут я даже твой контроллер возьму):
    получаем язык из гет-параметра
    PHP:
    1. function indexAction($smarty) { // параметром передаю ему объект smarty
    2.     $lang = $_GET['lang'];
    3. //тут будут манипуляции с языком, чуть дальше опишу
    4.       $itemId = isset($_GET['id']) ? $_GET['id'] : null;
    5.       if($itemId == null) exit();
    6. $rsProduct = getProductById($itemId);
    7. $smarty->assign('rsProduct', $rsProduct);
    вот, язык приняли. Допустим, у нас есть таблица в бд, которая содержит имя (ну неважно, это чисто для примера). В этой таблице 3 поля: id, name_ru, name_en. Т.е. у нас два языка. (тут реализовано может быть вообще как угодно. Главное сам принцип)
    Теперь учитывая язык выберем имя из базы данных, т.е.
    $name = select * from table;
    ассоциативный массив и тд и тп,
    а в шаблонизатор передаём типо так:
    PHP:
    1. $smarty->assign('name', $name['name_' . $lang]);
    т.е. шаблонизатор в принципе не знает, что есть несколько языков. Он только выводит name. А вот что будет в этом name - решает обработчик
    --- Добавлено ---
    PS: это примитивно-хреновая реализация. Я описал вообще приблизительный принцип работы. Так-то надо подумать над этим получше, улучшить и тд
     
  19. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    а что на счет: HTTP_ACCEPT_LANGUAGE? его не где прописывать не надо?
     
  20. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    ну в том случае, что мы щас пообсуждали, то нет.
    Я вообще, если честно, первый раз на практике сталкиваюсь с такими заголовками. Слышать слышал, но в пользовании не видел.
    Может я херовый прогер, конечно.
    А так, с этим заголовком происходит всё тоже самое, что я написал выше, только язык берётся не из гета, а из заголовка. Ну и да, заголовок тогда нужно будет отправлять на каждую страницу. Можешь и так сделать, в принципе. Но я бы не заморачивался.
    А можешь вообще тупо сессию создать и всё. При первом входе записать в сессию стандартный язык (русский, например). Если человек меняет язык - контроллер обрабатывает запрос и пишет в переменную сессионную новый язык. Тогда уже язык брать не из гета, а из сессии.
    А вообще, сделай сначала через гет. Просто чтобы понять как это будет работать. Переписать потом под сессии или заголовок, да или даже роутер - несложно. Ну, в принципе там переписана будет только строчка с получением и установкой языка.
     
  21. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    окей, сейчас попробую, посмотрю что получиться) спасибо) если что отпишу)
     
  22. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    скажи мне плз, а вот в шаблоне в файле tpl, как вывести тогда вот так: {$item['NAME_' $lang]}?
    ранее я так выводил: {$item['NAME_RUS']}
     
  23. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    @AlexsaiL, не. я думал я описал так, что ты понял. Но походу нет =D
    смотри. Шаблонизатор не должен знать ничего о языке.
    вот строка, которая была у тебя
    PHP:
    1. $smarty->assign('rsProduct', $rsProduct);
    этим ты передаёшь в шаблонизатор переменную rsProduct, в шаблонизаторе она будет иметь значение такое, которое у тебя лежит в контроллере в переменной $rsProduct
    дальше, смотри
    PHP:
    1. $smarty->assign('name', $name['name_' . $lang]);
    тут мы передаёт в шаблонизатор переменную name, а значение у неё будет $name['name_' . $lang]
    т.е. допустим, если подняться к коду выше ($name = select * from table;), из базы данных мы получили такой массив:
    PHP:
    1. $name = ["id" => "1", "name_ru" = > "русское имя", "name_en" => "английское имя"];
    а в шаблонизатор мы передаём: $name['name_' . $lang]
    т.е. если у нас $lang = ru, то в шаблонизатор уйдёт $name['name_ru'], если en, то $name['name_en' ]. Но! Шаблонизатор не знает этих переменных, он знает только свою переменную name. А значение этой переменной мы указываем в контроллере этой строчкой
    PHP:
    1. $smarty->assign('name', $name['name_' . $lang]);
    Вот я к чему. Разруливаем все вопросы, касаемо языка, в обработчиках. А в шаблонизатор только выведет переменную name. А вот что в ней будет храниться - решит в данном случае контроллер
     
  24. AlexsaiL

    AlexsaiL Активный пользователь

    С нами с:
    23 дек 2016
    Сообщения:
    327
    Симпатии:
    23
    все сделал как тут, но что то не работает, только пустой массив приходит, хз, может что то пропустил o_O:D
     
  25. acho

    acho Активный пользователь

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    @AlexsaiL, так покаж, как ты сделал. И схему таблицы