Multi Language

Dil değiştirdiğimizde site anasayfaya gitmeden, aynı bölümün değişen dil versiyonu ile gelmesini istersek, bu sistemi en iyi hangi yol ile yapılabilir. Birtürlü en iyi yola karar veremedim. Birçok yolu var, neye göre katogorize etmeliyim, sistemi nasıl koymak daha iyi, daha düzgün olur ?

Sessionda ana dili tutuyoruz. Controllerda sessiondaki değere göre bir işlem yaptırmalı. Viewları ona göre kaydetmeliki bir değişiklik ile dil direk değişmeli. Bu konuda hertürlü fikire açığım. Teşekküler.

herzaman daha iyi bir çözüm vardır ama benim önerim:

1- /protected/messages/ klasörü altında dil klasörlerini oluştur(Türkçe için tr_tr).




/protected/messages/

   tr_tr/

      translations.php

      yii.php

      zii.php



translations.php:




<?

   return array(

      'Hello World'=>'Merhaba Dünya',

      //bla bla..

   );

?>



yii.php : Bu dosya framework’ün içinde var. Türkçesini senin çevirmen lazım. uyarı mesajları için.

zii.php : yii.php ile aynı mantık

2- Konfigürasyon ayarları: language özelliğini varsayılan dile ayarla. Örneğin varsayılan dilimiz ingilizce olsun.




/protected/config/main.php

   return array(

         //bla bla..

         'language'=>'en_us',

         //bla bla...

   );      



3- Merhaba dünya! Herhangi bir view de dilden bağımsız kodlamaya başlayabiliriz artık Yii:t() ile.




/protected/views/site/pages/index.php

        //bla bla..

	Yii::t('translations','Hello World');

	//bla bla..



Bu kod ekrana ingilizce olarak "Hello World" yazdı. Şimdi dili istediğimiz zaman değiştirelim.

4- Kullanıcının giriş yapmasıyla session’a varsayılan dili kayıt edelim. Ben UserIdentity componentini kullanıyorum ve HttpSession a atıyorum. Bu kısmı dilediğin gibi yazabilirsin.




/protected/components/UserIdentity.php

        class UserIdentity extends CUserIdentity

	{

		public function authenticate()

		{

			//kullanıcı tanımlı ve şifre doğru ise..

			//session'a ekle

			$session = new CHttpSession;

			$session->open();

			$session['lang'] = Yii::app()->getLanguage();

			//diğer işlemler

		}

	}




5 - Ana sayfamıza dil değiştirme action’ı tanımlıyorum. Artık action sana nerde gerekiyorsa. Dikkat edersen bu kontrol CController’dan değil Controller’dan türüyor bu 6. madde de gerekecek.




/protected/controllers/SiteController.php

        class SiteController extends Controller

	{

		public function actionChangeLanguage()

		{

			//değişen dil parametresini al.

			$lang = $_GET['lang'];

			//sessiona ekle

			Yii::app()->session->add('lang',$lang);

			//uygulamanın dilini değiştir

			Yii::app()->setLanguage($lang);

                           

                        //view

                        $this->render('/site/index');			

		}

	}




6- Sanırım senin asıl sorduğun çözüm için önerim bu madde. Bütün controller ları default bir controllerdan türetirsen. beforeAction özelliğini kullanabilirsin.

Her action çalışmadan önce bu metodu çağırır sen de varsayılan dili burada ayarlarsın.




/protected/components/controller.php

        class Controller extends CController

	{

		public function beforeAction()

		{

			//uygulamanın dilini session kullanarak değiştir

			Yii::app()->setLanguage(Yii::app()->session['lang']);

			return true;

		}

	}




Şimdi adres çubuğundan bile dil değişimini deneyebilirsin. (not: urlManager aktif konfigürasyonumda)




Türkçe için: 

http://hostname/proje/index.php/site/changeLanguage/lang/tr_tr

İngilizce için: 

http://hostname/proje/index.php/site/changeLanguage/lang/en_us



eklemeler süslemeler sana kalmış artık :)

Yazdığın çok güzel bir yöntem ve teşekkür ederim. Bende site içersindeki mesajları, menu isimlerini bu şekilde kaydedip çağırmayı düşünüyordum.

Ancak içerikleri getirmeyi şöyle düşünüyorum, sessionda dili tutmak tamam. Menü veya uyarı mesajları dışında içeriği getirirken,

viewların içersinde;

-> site/tr/index.php

-> site/tr/pages/about.php

-> site/en/index.php

-> site/en/pages/about.php <-- gibi katagorize edip.

$this->render(Yii::app()->session[‘lang’].’/index’); <- diyerek çağırmayı düşünüyorum. Sen ne dersin ?

Dil değiştirmede function içersinde gelen dili okuyup sessiona yazıyorum sonrasında

$this->redirect(Yii::app()->getRequest()->urlReferrer); yönlendirmesi ile hangi sayfadan dil değiştirmesi isteniyorsa o sayfaya tekrar yöneliyor. Düzgün çalışıyor, ileride hesaplamadığım bir sorun çıkmaz umarım.

Tekrar teşekkürler paylaşımların için!!

Daha önce dediğim gibi herzaman daha iyi bir çözüm vardır :)

Eğer view sayfaların çok fazla php kodu içermiyorsa bu yöntem uygun ancak php kodu çok ise her dil klasörü için o kodları tekrarlaman gerekecek. Bu da kodda güncelleme yapılacağında can sıkıcı olabilir.

Contentlerde sadece içerik geliyor. Genelde contentlerde yazılar var. Model ve controller aracılıyla sadece gerekli veriler yollanıyor içeriğe. Belki birgün daha iyi bir yönetem öğrenirim yada keşfederim o zaman ona uyarlarım. Fakat şimdilik bu yöntem sorunsuz çalışıyor. Baya geç cevap yazdım mazur gör iş yoğunluğu. :)

Dil değişimi için client tarafına cookie atabilirsiniz. Session düştüğünde dil öntanımlı değere dönmez.


<?php


/**

 * Manage cookies

 */

class MCookie {


   /**

    * Get a cookie value

    * @param string $name

    * @return string

    */

   public static function get($name) {

      $cookies = Yii::app()->request->getCookies();

      return is_object($cookies[$name]) ? $cookies[$name]->value : null;

   }


   /**

    * Whether has a cookie

    * @param string $name

    * @return bool

    */

   public static function has($name) {

      $cookies = Yii::app()->request->getCookies();

      return is_object($cookies[$name]);

   }


   /**

    * Set a cookie value

    * @param string $name

    * @param string $value

    * @param array $params

    */

   public static function set($name, $value, $params=array()) {

      $cookie = new CHttpCookie($name, $value);

      $cookie->expire = time() + 3600 * 24 * 30; // by default to 30 days from now

      if (isset($params['expire'])) {

         if (is_numeric($params['expire'])) {

            $cookie->expire = (int) $params['expire'];

            // don't forget, expire is a timestamp

            $cookie->expire < time() && ($cookie->expire += time());

         } else {/* write log */

         }

      }

      if (isset($params['domain'])) {

         if (is_string($params['domain']) || is_numeric($params['domain']))

            $cookie->domain = (string) $params['domain'];

         else {/* write log */

         }

      }

      if (isset($params['path'])) {

         if (is_string($params['path']) || is_numeric($params['path']))

            $cookie->path = (string) $params['path'];

         else {/* write log */

         }

      }

      if (isset($params['secure'])) {

         if (is_bool($params['secure']))

            $cookie->secure = $params['secure'];

         else {/* write log */

         }

      }

      if (isset($params['httpOnly'])) {

         if (is_bool($params['httpOnly']))

            $cookie->httpOnly = $params['httpOnly'];

         else {/* write log */

         }

      }

      $cookies = Yii::app()->request->getCookies();

      $cookies[$name] = $cookie;

   }


   /**

    * Unset a cookie

    * @param string $name

    */

   public static function unsetIt($name) {

      $cookies = Yii::app()->request->getCookies();

      unset($cookies[$name]);

   }


}