对于多语言网站,我们可以用 en.fecshop.com,fr.fecshop.com,es.fecshop.com, 这种子域名的方式表现做多语言
也可以用 www.fecshop.com , www.fecshop.com/fr , www.fecshop.com/es , 这种方式做多语言
yii2对第一种支持还是不错,对于第二种支持不好,我们搞一种自己的方式来支持这种。
1.在app/web/下面新建文件夹
app/web/fr
app/web/es
在上面的文件夹下面新建index.php文件,assets文件夹设置可写。
/app/web/fr/index.php
1.nginx设置:
在nginx的server配置中加入:
location /fr/ { index index.php; if (!-e $request_filename){ rewrite . /fr/index.php last; } }
2.入口/app/web/fr/index.php文件开始加入:
$secure = 0; $http = $secure ? 'https' : 'http'; $homeUrl = $http.'://'.$_SERVER['HTTP_HOST'].rtrim(dirname($_SERVER['SCRIPT_NAME']), '\\/');
$application = new yii\web\Application($config);
的上面加入:
$config['homeUrl'] = $homeUrl;
加完之后的样子:
<?php //$secure = isset($_SERVER['HTTPS']) && (strcasecmp($_SERVER['HTTPS'], 'on') === 0 || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0; $secure = 0; $http = $secure ? 'https' : 'http'; $homeUrl = $http.'://'.$_SERVER['HTTP_HOST'].rtrim(dirname($_SERVER['SCRIPT_NAME']), '\\/'); defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require(__DIR__ . '/../../../vendor/autoload.php'); require(__DIR__ . '/../../../vendor/yiisoft/yii2/Yii.php'); require(__DIR__ . '/../../../common/config/bootstrap.php'); require(__DIR__ . '/../../config/bootstrap.php'); $config = yii\helpers\ArrayHelper::merge( require(__DIR__ . '/../../../common/config/main.php'), require(__DIR__ . '/../../../common/config/main-local.php'), require(__DIR__ . '/../../config/main.php'), require(__DIR__ . '/../../config/main-local.php') ); $config['homeUrl'] = $homeUrl; $application = new yii\web\Application($config); $application->run();
3.添加store组件:
'store' => [ 'class' => 'fecshop\services\Store', 'stores' => [ 'fecshop.appadmin.fancyecommerce.com/fr' => [ 'language' => 'fr', 'themePackage' => 'default', 'theme' => 'default', 'currency' => 'USD', ], 'fecshop.appadmin.fancyecommerce.com/es' => [ 'language' => 'es', 'themePackage' => 'default', 'theme' => 'default', 'currency' => 'USD', ], 'fecshop.appadmin.fancyecommerce.com' => [ 'language' => 'en', 'themePackage' => 'default', 'theme' => 'default', 'currency' => 'USD', ], ], 'languages' => [ //'en','fr','it','de','es','nl','pt','ru', ], ],
组件:
<?php /** * FecShop file. * * @link http://www.fecshop.com/ * @copyright Copyright (c) 2016 FecShop Software LLC * @license http://www.fecshop.com/license/ */ namespace fecshop\services; use Yii; use yii\base\InvalidValueException; use yii\base\InvalidConfigException; use yii\base\BootstrapInterface; /** * @author Terry Zhao <2358269014@qq.com> * @since 1.0 */ class Store extends Service implements BootstrapInterface { /** * init by config file. * all stores config . include : domain,language,theme,themePackage */ public $stores; /** * init by config file. * all store Language. */ public $languages; /** * current store language */ public $currentLanguage = 'en'; /** * current store theme package */ public $currentThemePackage = 'default'; /** * current store theme */ public $currentTheme = 'default'; /** * current store name , this property will init value with domain. */ public $currentStore; /** * Bootstrap:init website, class property $currentLanguage ,$currentTheme and $currentStore. * if you not config this ,default class property will be set. * if current domain is not config , InvalidValueException will be throw. * class property $currentStore will be set value $domain. */ public function bootstrap($app){ $host = explode('://' ,$app->getHomeUrl()); $stores = $this->stores; $init_compelte = 0; if(is_array($stores) && !empty($stores)){ foreach($stores as $domain => $lang){ if($host[1] == $domain){ Yii::$app->store->currentStore = $domain; if(isset($lang['language']) && !empty($lang['language'])){ Yii::$app->store->currentLanguage = $lang['language']; } if(isset($lang['theme']) && !empty($lang['theme'])){ Yii::$app->store->currentTheme = $lang['theme']; } if(isset($lang['themePackage']) && !empty($lang['themePackage'])){ Yii::$app->store->currentThemePackage = $lang['themePackage']; } /** * init store currency. */ if(isset($lang['currency']) && !empty($lang['currency'])){ $currency = $lang['currency']; }else{ $currency = ''; } Yii::$app->page->currency->initCurrency($currency); /** * current domian is config is store config. */ $init_compelte = 1; } } } if(!$init_compelte){ throw new InvalidValueException('this domain is not config in store component'); } } /** * if a object or array attribute is a store attribute, you can get current * language value by this function. */ public function getLangVal($attr,$attrName){ return $attr[$this->currentLanguage."_".$attrName]; } public function getAllLanguage(){ } }
上面通过相应的域名设置不同的语言,货币,模板等。
4.yii的yii\helpers\Url已经对我们不适合,我们需要自己写一个url的生成:
<?php namespace fec\helpers; use Yii; class CUrl { public static $_baseHttpUrl; public static $_baseHttpsUrl; # 1.获取首页地址。 public static function getHomeUrl(){ return Yii::$app->getHomeUrl(); //return Yii::$app->getBaseUrl(true); } # 2. 获取首页地址。同上 public static function getBaseUrl($isHttps=false){ if($isHttps){ if(!self::$_baseHttpsUrl){ self::$_baseHttpsUrl = str_replace('http','https',self::getHomeUrl()); } return self::$_baseHttpsUrl; }else{ if(!self::$_baseHttpUrl){ self::$_baseHttpUrl = str_replace('https','http',self::getHomeUrl()); } return self::$_baseHttpUrl; } } # 3.立即跳转 和 yii2的跳转还是不同 public static function redirect($url,$isHttps=false){ if($url){ if(substr($url,0,4) != "http"){ $url = self::getUrl($url,[],$isHttps); } header("Location: $url"); exit; } } # 4.通过模板name,得到对应文件路径。 # 默认是 domain.com/skin/theme/下面的绝对URL public static function getSkinUrl($dir = '',$relative_path=false){ $currentTheme = CConfig::getCurrentTheme(); $url = ''; if(!$relative_path){ $url = self::getHomeUrl(). DIRECTORY_SEPARATOR; } return $url.'skin'.DIRECTORY_SEPARATOR .$currentTheme.DIRECTORY_SEPARATOR .$dir; } #5. 通过url path 和参数 得到当前网站下的完整url路径。 public static function getUrl($url_path,$params=array(),$isHttps=false){ $url_path = trim($url_path,DIRECTORY_SEPARATOR); $url = self::getBaseUrl($isHttps). DIRECTORY_SEPARATOR .$url_path; $str = ""; if(!empty($params) && is_array($params)){ $str .= "?"; foreach($params as $k=>$v){ $str .= $k."=".$v."&"; } $str = substr($str,0,strlen($str)-1); } return $url.$str; } # 6.得到当前的完整url public static function getCurrentUrl(){ //$s = self::getHomeUrl(); //return $s.$_SERVER["REQUEST_URI"]; return \yii\helpers\Url::current(); } # 7.得到当前的完整url no param public static function getCurrentUrlNoParam(){ $url = self::getCurrentUrl(); if(strstr($url,"#")){ $url = substr($url,0,strpos($url,"#")); } if(strstr($url,"?")){ $url = substr($url,0,strpos($url,"?")); } return $url; } # 8、得到url key ,譬如 http://www.x.com/ss/dd/aa?aaaa=ddddd 返回 /ss/dd/aa public static function getUrlKey(){ return Yii::$app->request->getPathInfo(); } # 9.得到url ,譬如 http://www.x.com/ss/dd/aa?aaaa=ddddd 返回 /ss/dd/aa?aaaa=ddddd public static function getUrlKeyWithParam(){ return Yii::$app->getRequest()->url; } }
得到url:
CUrl::getUrl('/x/x/x',['p'=>'2]); #将生成 http://fecshop.appadmin.fancyecommerce.com/fr/x/x/x?p=2 CUrl::getUrl('/x/x/x',['p'=>'2],rue); #将生成 https://fecshop.appadmin.fancyecommerce.com/fr/x/x/x?p=2
OK,到这里就完成整个过程了。
nginx 配置可以这么改
if ( $request_filename ~* \/(cn|en|tw)\/ ) {
set $webroot $1;
}
location / {
try_files $uri $uri/ /$webroot/index.php?$args;
}
嗯,有很多不同的写法