提交 5f3af2a6 编写于 作者: G gongfuxiang

新增系统内置多语言切换

上级 90eead19
......@@ -19,6 +19,7 @@ use app\service\AdminPowerService;
use app\service\ConfigService;
use app\service\ResourcesService;
use app\service\StoreService;
use app\service\MultilingualService;
/**
* 管理员公共控制器
......@@ -105,6 +106,9 @@ class Common extends BaseController
// 系统初始化
$this->SystemInit();
// 系统运行开始
SystemService::SystemBegin($this->data_request);
// 管理员信息
$this->admin = AdminService::LoginInfo();
......@@ -122,6 +126,20 @@ class Common extends BaseController
$this->CommonPluginsInit();
}
/**
* 析构函数
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-03-18
* @desc description
*/
public function __destruct()
{
// 系统运行结束
SystemService::SystemEnd($this->data_request);
}
/**
* 系统初始化
* @author Devil
......@@ -372,6 +390,10 @@ class Common extends BaseController
// 省市联动是否必选选择
$assign['is_force_region_choice'] = 1;
// 多语言
$assign['multilingual_default_code'] = MultilingualService::GetUserMultilingualValue();
$assign['multilingual_data'] = MultilingualService::MultilingualData();
// 模板赋值
MyViewAssign($assign);
}
......
......@@ -57,7 +57,7 @@ class Theme extends Base
// 导航参数
'view_type' => $this->view_type,
// 基础导航
'base_nav' => MyLang('appmini.base_nav_list'),
'base_nav' => MyLang('theme.base_nav_list'),
// 应用商店
'store_theme_url' => StoreService::StoreThemeUrl(),
];
......
......@@ -204,7 +204,7 @@ return [
'3. The style of the front category page will be different if the level is different',
],
'goods_auto_mode_max_count_tips_list' => [
'1. Configure the maximum number of products displayed on each floor',
'1. Configure the maximum number of goods displayed on each floor',
'2. It is not recommended to modify the quantity too large, which will lead to too large blank area on the left side of the PC',
],
'goods_auto_mode_order_by_tips_list' => [
......@@ -212,7 +212,7 @@ return [
],
'goods_manual_mode_max_tips_list' => [
'1. Click the title of the item to drag and sort it and display it in order',
'2. It is not recommended to add many products, which will lead to too large blank area on the left side of the PC',
'2. It is not recommended to add many goods, which will lead to too large blank area on the left side of the PC',
],
'extends_crontab_tips' => 'It is recommended that you add the script address to the timing request of the Linux scheduled task (the result is SUCS: 0, FAIL: 0, followed by the colon is the number of data processed, SUCS succeeded, FALI failed)',
'left_images_random_tips' => 'The left picture can upload up to 3 pictures, and one of them can be displayed randomly each time',
......@@ -225,7 +225,7 @@ return [
'site_setup_choice_payment_message' => 'Please select {:name} default payment method',
'sitetype_top_tips_list' => [
'1. Express delivery, conventional e-commerce process, user selects the receiving address to place an order for payment ->merchant shipment ->confirmation of receipt ->order completion',
'2. Display type, only display products, can initiate consultation (cant place an order)',
'2. Display type, only display goods, can initiate consultation (cant place an order)',
'3. Select the self-pickup address when placing the order, and the user places the order for payment ->confirm the delivery ->order completion',
'4. Virtual sales, conventional e-commerce process, user order payment ->automatic delivery ->confirmation of delivery ->order completion',
],
......@@ -410,7 +410,7 @@ return [
// 动态表格
'form_table' => [
'goods' => 'Base Info',
'goods_placeholder' => 'Please enter the product name/model',
'goods_placeholder' => 'Please enter the goods name/model',
'warehouse_name' => 'Warehouse',
'is_enable' => 'Enable or not',
'inventory' => 'Total Inventory',
......@@ -430,9 +430,9 @@ return [
],
'base_nav_title' => 'Admin',
// 登录
'login_type_username_title' => 'Account Password',
'login_type_mobile_title' => 'Mobile Verify Code',
'login_type_email_title' => 'Email Verify Code',
'login_type_username_title' => 'Account',
'login_type_mobile_title' => 'Mobile',
'login_type_email_title' => 'Email',
'login_close_tips' => 'Temporarily closed login',
// 忘记密码
'form_forget_password_name' => 'Forgot Password?',
......@@ -486,9 +486,10 @@ return [
'nav_theme_download_tips' => 'The theme of mobile phone is developed by uniapp (supporting multi-terminal applet+H5), and APP is also in emergency adaptation。',
'form_alipay_extend_title' => 'Customer service configuration',
'form_alipay_extend_tips' => 'PS: If [APP/applet] is enabled (online customer service is enabled), the following configuration must be filled in [Enterprise Code] and [Chat Window Code]',
'form_theme_upload_tips' => 'Upload a zip compressed installation package',
'list_no_data_tips' => 'No related theme packs',
'list_author_title' => 'Author',
'list_version_title' => 'Applicable version',
'list_author_title' => 'Author',
'list_version_title' => 'Applicable version',
'package_generate_tips' => 'The generation time is relatively long, please do not close the browser window!',
// 动态表格
'form_table' => [
......@@ -588,7 +589,7 @@ return [
'user' => 'User Info',
'user_placeholder' => 'Please enter user name/nickname/mobile phone/email',
'goods' => 'Base Info',
'goods_placeholder' => 'Please enter the product name/model',
'goods_placeholder' => 'Please enter the goods name/model',
'business_type' => 'Business Type',
'content' => 'Content',
'images' => 'Images',
......@@ -770,7 +771,7 @@ return [
// 动态表格
'form_table' => [
'goods' => 'Base Info',
'goods_placeholder' => 'Please enter order ID/order number/product name/model',
'goods_placeholder' => 'Please enter order ID/order number/goods name/model',
'user' => 'User Info',
'user_placeholder' => 'Please enter user name/nickname/mobile phone/email',
'status' => 'Order Status',
......@@ -820,7 +821,7 @@ return [
// 动态表格
'form_table' => [
'goods' => 'Base Info',
'goods_placeholder' => 'Please enter the order number/product name/model',
'goods_placeholder' => 'Please enter the order number/goods name/model',
'user' => 'User Info',
'user_placeholder' => 'Please enter user name/nickname/mobile phone/email',
'status' => 'Status',
......@@ -896,9 +897,9 @@ return [
['name' => 'Theme Install', 'type' => 'upload'],
],
'nav_store_theme_name' => 'More topic downloads',
'list_author_title' => 'Author',
'list_author_title' => 'Author',
'list_version_title' => 'Applicable Version',
'form_item_upload_tips' => 'Upload an application installation package in zip compression format',
'form_theme_upload_tips' => 'Upload a zip compressed theme installation package',
],
// 用户中心导航
......@@ -1027,9 +1028,9 @@ return [
'base_top_tips_one' => 'List sorting method [custom sorting ->earliest installation]',
'base_top_tips_two' => 'Click and drag icon button to adjust plug-in call and display order',
'base_open_sort_title' => 'Enable sorting',
'data_list_author_title' => 'Author',
'data_list_author_url_title' => 'HomePage',
'data_list_version_title' => 'Version',
'data_list_author_title' => 'Author',
'data_list_author_url_title' => 'HomePage',
'data_list_version_title' => 'Version',
'uninstall_confirm_tips' => 'Uninstallation may lose the basic configuration data of the plug-in. Is it unrecoverable and confirm the operation?',
'not_install_divide_title' => 'The following plugins are not installed',
'delete_plugins_text' => '1. Delete apps only',
......@@ -1198,7 +1199,7 @@ return [
'1. All (displayed under goods basic information and detail parameters)',
'2. Details (only displayed under the goods details parameter)',
'3. Basic (only displayed under goods basic information)',
'4. The shortcut operation will clear the original data and reload the page to restore the original data (only effective after saving the product)',
'4. The shortcut operation will clear the original data and reload the page to restore the original data (only effective after saving the goods)',
],
],
......@@ -1222,7 +1223,7 @@ return [
'item' => [
'site_index' => 'Site setup',
'site_save' => 'Site setup editing',
'site_goodssearch' => 'Site setup and product search',
'site_goodssearch' => 'Site setup and goods search',
'layout_layoutindexhomesave' => 'Homepage layout admin',
'sms_index' => 'SMS setup',
'sms_save' => 'SMS setup editing',
......
......@@ -485,9 +485,10 @@ return [
'nav_theme_download_tips' => '手机端主题采用uniapp开发(支持多端小程序+H5),APP也在紧急适配中。',
'form_alipay_extend_title' => '客服配置',
'form_alipay_extend_tips' => 'PS:如【APP/小程序】中开启(开启在线客服),则以下配置必填 [企业编码] 和 [聊天窗编码]',
'form_theme_upload_tips' => '上传一个zip压缩格式的安装包',
'list_no_data_tips' => '没有相关主题包',
'list_author_title' => '作者',
'list_version_title' => '适用版本',
'list_author_title' => '作者',
'list_version_title' => '适用版本',
'package_generate_tips' => '生成时间比较长,请不要关闭浏览器窗口!',
// 动态表格
'form_table' => [
......@@ -881,9 +882,9 @@ return [
['name' => '主题安装', 'type' => 'upload'],
],
'nav_store_theme_name' => '更多主题下载',
'list_author_title' => '作者',
'list_version_title' => '适用版本',
'form_item_upload_tips' => '上传一个zip压缩格式的应用安装包',
'list_author_title' => '作者',
'list_version_title' => '适用版本',
'form_theme_upload_tips' => '上传一个zip压缩格式的主题安装包',
],
// 用户中心导航
......@@ -1012,9 +1013,9 @@ return [
'base_top_tips_one' => '列表排序方式[ 自定义排序 -> 最早安装 ]',
'base_top_tips_two' => '可点击拖动图标按钮调整插件调用和展示顺序',
'base_open_sort_title' => '开启排序',
'data_list_author_title' => '作者',
'data_list_author_url_title' => '主页',
'data_list_version_title' => '版本',
'data_list_author_title' => '作者',
'data_list_author_url_title' => '主页',
'data_list_version_title' => '版本',
'uninstall_confirm_tips' => '卸载可能会丢失插件基础配置数据不可恢复、确认操作吗?',
'not_install_divide_title' => '以下插件未安装',
'delete_plugins_text' => '1. 仅删除应用',
......
......@@ -58,7 +58,7 @@
{{/if}}
<div class="am-form-group am-form-group-refreshing am-margin-top-lg">
<input type="hidden" name="type" value="username" />
<button type="submit" class="am-btn am-btn-primary am-btn-block am-radius am-btn-sm btn-loading-example" data-am-loading="{loadingText: '{{:MyLang('processing_tips')}}'}'}">{{:MyLang('login_title')}}</button>
<button type="submit" class="am-btn am-btn-primary am-btn-block am-radius am-btn-sm btn-loading-example" data-am-loading="{loadingText: '{{:MyLang('processing_tips')}}'}">{{:MyLang('login_title')}}</button>
</div>
</form>
<!-- form end -->
......@@ -84,7 +84,7 @@
</div>
<div class="am-form-group am-form-group-refreshing am-margin-top-lg">
<input type="hidden" name="type" value="sms" />
<button type="submit" class="am-btn am-btn-primary am-btn-block am-radius am-btn-sm btn-loading-example" data-am-loading="{loadingText: '{{:MyLang('processing_tips')}}'}'}">{{:MyLang('login_title')}}</button>
<button type="submit" class="am-btn am-btn-primary am-btn-block am-radius am-btn-sm btn-loading-example" data-am-loading="{loadingText: '{{:MyLang('processing_tips')}}'}">{{:MyLang('login_title')}}</button>
</div>
</form>
<!-- form end -->
......@@ -110,7 +110,7 @@
</div>
<div class="am-form-group am-form-group-refreshing am-margin-top-lg">
<input type="hidden" name="type" value="email" />
<button type="submit" class="am-btn am-btn-primary am-btn-block am-radius am-btn-sm btn-loading-example" data-am-loading="{loadingText: '{{:MyLang('processing_tips')}}'}'}">{{:MyLang('login_title')}}</button>
<button type="submit" class="am-btn am-btn-primary am-btn-block am-radius am-btn-sm btn-loading-example" data-am-loading="{loadingText: '{{:MyLang('processing_tips')}}'}">{{:MyLang('login_title')}}</button>
</div>
</form>
<!-- form end -->
......
......@@ -34,14 +34,14 @@
{{/if}}
</div>
</h3>
<div class="am-gallery-desc">{{:MyLang('appmini.list_author_title')}}
<div class="am-gallery-desc">{{:MyLang('appmini.list_author_title')}}
{{if empty($v['home'])}}
{{$v.author}}
{{else /}}
<a href="{{$v.home}}" target="_blank">{{$v.author}}</a>
{{/if}}
</div>
<div class="am-gallery-desc">{{:MyLang('appmini.list_version_title')}}{{$v.ver}}</div>
<div class="am-gallery-desc">{{:MyLang('appmini.list_version_title')}}{{$v.ver}}</div>
</div>
</div>
</li>
......
......@@ -17,7 +17,7 @@
<button type="button" class="am-btn am-btn-default am-btn-sm am-radius">
<i class="am-icon-cloud-upload"></i> {{:MyLang('form_choice_images_title')}}</button>
<input type="file" name="theme" class="file-event" data-tips-tag="#form-theme-tips" data-validation-message="{{:MyLang('form_upload_file_message')}}" accept=".zip" required />
<span class="tips am-text-xs">{{:MyLang('appmini.form_item_upload_file_tips')}}</span>
<span class="tips am-text-xs">{{:MyLang('appmini.form_theme_upload_tips')}}</span>
<div id="form-theme-tips" class="am-margin-top-xs"></div>
</div>
</div>
......
......@@ -20,14 +20,30 @@
<!-- 右侧内容 -->
<div class="am-collapse am-topbar-collapse" id="topbar-collapse">
<ul class="am-nav am-nav-pills am-topbar-nav am-topbar-right admin-header-list tpl-header-list">
<li class="am-dropdown">
{{if !empty($multilingual_data) and !empty($multilingual_data['data']) and !empty($multilingual_data['default']) and is_array($multilingual_data['data']) and is_array($multilingual_data['default'])}}
<li class="am-dropdown common-nav-top" data-am-dropdown data-am-dropdown-toggle>
<a class="am-dropdown-toggle" href="javascript:;">
<i class="am-icon-language"></i>
<span>{{:MyLang('lang_title')}}[{{$multilingual_data.default.name}}]</span>
</a>
<ul class="am-dropdown-content am-radius">
{{foreach $multilingual_data.data as $v}}
<li>
<a href="{{$v.url}}">{{$v.name}}</a>
</li>
{{/foreach}}
</ul>
</li>
{{/if}}
<li>
<a href="{{$theme_color_url}}">
<i class="am-icon-adjust"></i>
<span>{{$theme_color_name}}</span>
</a>
</li>
{{if AdminIsPower('cache', 'statusupdate')}}
<li class="am-dropdown">
<li>
<a href="javascript:;" class="submit-ajax" data-url="{{:MyUrl('admin/cache/statusupdate')}}" data-is-confirm="0" data-is-loading="1">
<i class="am-icon-paint-brush"></i>
<span>{{:MyLang('common.remove_cache_title')}}</span>
......@@ -42,7 +58,7 @@
</a>
</li>
<li class="am-dropdown">
<li>
<a href="{{$home_url}}" target="_blank">
<i class="am-icon-home"></i>
<span>{{:MyLang('shop_home_title')}}</span>
......@@ -56,7 +72,7 @@
<span class="tpl-header-list-user-ico">
</span>
</a>
<ul class="am-dropdown-content">
<ul class="am-dropdown-content am-radius">
<li>
<a href="javascript:;" data-type="nav" data-url="{{:MyUrl('admin/admin/saveInfo', array('id'=>$admin['id']))}}" data-node-name="{{:MyLang('setup_title')}}">
<i class="am-icon-cog"></i>
......
......@@ -31,14 +31,14 @@
{{/if}}
</div>
</h3>
<div class="am-gallery-desc">{{:MyLang('theme.list_author_title')}}
<div class="am-gallery-desc">{{:MyLang('theme.list_author_title')}}
{{if empty($v['home'])}}
{{$v.author}}
{{else /}}
<a href="{{$v.home}}" target="_blank">{{$v.author}}</a>
{{/if}}
</div>
<div class="am-gallery-desc">{{:MyLang('theme.list_version_title')}}{{$v.ver}}</div>
<div class="am-gallery-desc">{{:MyLang('theme.list_version_title')}}{{$v.ver}}</div>
</div>
</div>
</li>
......
......@@ -14,7 +14,7 @@
<button type="button" class="am-btn am-btn-default am-btn-sm am-radius">
<i class="am-icon-cloud-upload"></i> {{:MyLang('form_choice_images_title')}}</button>
<input type="file" name="theme" class="file-event" data-tips-tag="#form-theme-tips" data-validation-message="{{:MyLang('form_upload_file_message')}}" accept=".zip" required />
<span class="tips am-text-xs">{{:MyLang('theme.form_item_upload_tips')}}</span>
<span class="tips am-text-xs">{{:MyLang('theme.form_theme_upload_tips')}}</span>
<div id="form-theme-tips" class="am-margin-top-xs"></div>
</div>
</div>
......
......@@ -17,6 +17,7 @@ use app\service\PluginsService;
use app\service\ConstService;
use app\service\AdminService;
use app\service\AdminPowerService;
use app\service\MultilingualService;
/**
* 两个数组字段对比处理、arr1不存在arr2中的字段则移除
......@@ -164,15 +165,27 @@ function MyLang($key, $vars = [], $lang = '')
$value = '';
if(!empty($key))
{
// 当前语言
$current_lang = empty($lang) ? MultilingualService::GetUserMultilingualValue() : $lang;
// key使用 . 分隔
$key_arr = explode('.', $key);
// 语言数据容器
static $lang_data = [];
// 系统语言
$arr_file = [
APP_PATH.RequestModule().DS.'lang'.DS.$current_lang.'.php',
APP_PATH.'lang'.DS.$current_lang.'.php',
];
// 是否插件语言
if(RequestController() == 'plugins')
{
// 静态存储、不用每次都从磁盘读取
static $lang_data = [];
$file = APP_PATH.'plugins'.DS.MyInput('pluginsname').DS.'lang'.DS.MyConfig('lang.default_lang').'.php';
array_unshift($arr_file, APP_PATH.'plugins'.DS.MyInput('pluginsname').DS.'lang'.DS.$current_lang.'.php');
}
foreach($arr_file as $file)
{
$md5_key = md5($file);
if(!array_key_exists($md5_key, $lang_data) && file_exists($file))
{
......@@ -193,51 +206,36 @@ function MyLang($key, $vars = [], $lang = '')
if(array_key_exists($key_arr[0], $temp_lang_data))
{
$value = $temp_lang_data[$key_arr[0]];
}
// 移除第一级
array_shift($key_arr);
// 循环后面级别的数据
foreach($key_arr as $v)
{
if(is_array($value) && array_key_exists($v, $value))
if(!empty($value) && is_array($value))
{
$value = $value[$v];
} else {
// 未匹配到则赋空值
$value = $key;
break;
// 移除第一级
array_shift($key_arr);
// 循环后面级别的数据
foreach($key_arr as $v)
{
if(array_key_exists($v, $value))
{
$value = $value[$v];
} else {
// 未匹配到则赋空值
$value = $key;
break;
}
}
}
}
}
}
}
// 默认也从系统读取
// 插件未读取成功则从系统读取
if($value === '')
// 未找到对应语言
if($value == '' || $key == $value)
{
// 系统语言
// 仅一级则直接读取
if(count($key_arr) == 1)
// 非默认语言则读取默认语言
$default_lang = MyConfig('lang.default_lang');
if($default_lang != $lang)
{
$value = lang($key, [], $lang);
} else {
// 默认先读取第一级
$value = lang($key_arr[0], [], $lang);
// 移除第一级
array_shift($key_arr);
// 循环后面级别的数据
foreach($key_arr as $v)
{
if(isset($value[$v]))
{
$value = $value[$v];
} else {
// 未匹配到则赋空值
$value = $key;
break;
}
}
$value = MyLang($key, $vars, $default_lang);
}
}
......
......@@ -25,6 +25,7 @@ use app\service\ConfigService;
use app\service\UserService;
use app\service\AdminService;
use app\service\QuickNavService;
use app\service\MultilingualService;
/**
* 前端公共控制器
......@@ -457,6 +458,9 @@ class Common extends BaseController
// 省市联动是否必选选择
$assign['is_force_region_choice'] = 1;
// 多语言
$assign['multilingual_default_code'] = MultilingualService::GetUserMultilingualValue();
// 模板赋值
MyViewAssign($assign);
}
......
......@@ -20,7 +20,7 @@ return [
// 页面公共
'common' => [
// 公共
'shop_home_title' => 'Mall homepage',
'shop_home_title' => 'Mall Home',
'back_to_the_home_title' => 'Back to the home',
'all_category_text' => 'All Category',
'login_title' => 'Login',
......@@ -90,7 +90,7 @@ return [
'browser_seo_title' => 'Goods Category',
'no_category_data_tips' => 'No classification data',
'no_sub_category_data_tips' => 'No subcategory data',
'view_category_sub_goods_name' => 'View products under category',
'view_category_sub_goods_name' => 'View goods under category',
],
// 购物车
......@@ -193,7 +193,7 @@ return [
'detail_browser_seo_title' => 'Order Detail',
'comments_browser_seo_title' => 'Order Comments',
'batch_payment_name' => 'Batch Payment',
'comments_goods_list_thead_base' => 'Product information',
'comments_goods_list_thead_base' => 'Goods Info',
'comments_goods_list_thead_price' => 'Price',
'comments_goods_list_thead_content' => 'Comment Content',
'form_you_have_commented_tips' => 'You have commented',
......@@ -238,7 +238,7 @@ return [
// 动态表格
'form_table' => [
'goods' => 'Base Info',
'goods_placeholder' => 'Please enter the order number/product name/model',
'goods_placeholder' => 'Please enter the order number/goods name/model',
'status' => 'Order Status',
'pay_status' => 'Payment Status',
'total_price' => 'Total Price(yuan)',
......@@ -325,7 +325,7 @@ return [
// 动态表格
'form_table' => [
'goods' => 'Base Info',
'goods_placeholder' => 'Please enter the order number/product name/model',
'goods_placeholder' => 'Please enter the order number/goods name/model',
'status' => 'Status',
'type' => 'Apply Type',
'reason' => 'Reason',
......@@ -358,16 +358,16 @@ return [
// 登录
'login_top_register_tips' => 'Dont have an account yet?',
'login_close_tips' => 'Temporarily closed login',
'login_type_username_title' => 'Account Password',
'login_type_mobile_title' => 'Mobile Verify Code',
'login_type_email_title' => 'Email Verify Code',
'login_type_username_title' => 'Account',
'login_type_mobile_title' => 'Mobile',
'login_type_email_title' => 'Email',
'login_retrieve_password_title' => 'Retrieve Password',
// 注册
'register_top_login_tips' => 'I have registered, now',
'register_close_tips' => 'Registration is temporarily closed',
'register_type_username_title' => 'Account Register',
'register_type_mobile_title' => 'Mobile Register',
'register_type_email_title' => 'Email Register',
'register_type_username_title' => 'Account',
'register_type_mobile_title' => 'Mobile',
'register_type_email_title' => 'Email',
// 忘记密码
'forget_password_top_login_tips' => 'Already have an account?',
// 表单
......@@ -405,9 +405,9 @@ return [
'various_cart_tips' => 'Put the goods you want to buy into the shopping cart and make it easier to settle together',
'various_favor_title' => 'Goods Favor',
'various_favor_empty_title' => 'You havent collected any goods yet',
'various_favor_tips' => 'Favorite products will display the latest promotions and price reductions',
'various_favor_tips' => 'Favorite goods will display the latest promotions and price reductions',
'various_browse_title' => 'My Browse',
'various_browse_empty_title' => 'Your product browse record is empty',
'various_browse_empty_title' => 'Your goods browse record is empty',
'various_browse_tips' => 'Go to the mall to see the promotional activities',
],
......@@ -421,8 +421,8 @@ return [
'browser_seo_title' => 'My Browse',
// 动态表格统计数据
'form_table' => [
'goods' => 'Product information',
'goods_placeholder' => 'Please enter the product name/brief description/SEO information',
'goods' => 'Goods Info',
'goods_placeholder' => 'Please enter the goods name/brief description/SEO information',
'price' => 'Sales price (yuan)',
'original_price' => 'Original price (yuan)',
......@@ -435,8 +435,8 @@ return [
'browser_seo_title' => 'Goods Favor',
// 动态表格统计数据
'form_table' => [
'goods' => 'Product information',
'goods_placeholder' => 'Please enter the product name/brief description/SEO information',
'goods' => 'Goods Info',
'goods_placeholder' => 'Please enter the goods name/brief description/SEO information',
'price' => 'Sales price (yuan)',
'original_price' => 'Original price (yuan)',
......
......@@ -61,9 +61,9 @@
{{if !empty($user_order_status)}}
{{foreach $user_order_status as $v}}
{{if in_array($v['status'], [1,2,3])}}
<a href="{{:MyUrl('index/order/index', ['is_more'=>1, 'status'=>$v['status']])}}" target="_blank"><strong>{{$v.count}}</strong>{{$v.name}}</a>
<a href="{{:MyUrl('index/order/index', ['is_more'=>1, 'status'=>$v['status']])}}" class="am-text-truncate" target="_blank"><strong>{{$v.count}}</strong>{{$v.name}}</a>
{{elseif in_array($v['status'], [100]) /}}
<a href="{{:MyUrl('index/order/index', ['is_more'=>1, 'is_comments'=>0, 'status'=>4])}}" target="_blank"><strong>{{$v.count}}</strong>{{$v.name}}</a>
<a href="{{:MyUrl('index/order/index', ['is_more'=>1, 'is_comments'=>0, 'status'=>4])}}" class="am-text-truncate" target="_blank"><strong>{{$v.count}}</strong>{{$v.name}}</a>
{{/if}}
{{/foreach}}
{{/if}}
......
......@@ -29,13 +29,14 @@
[<a href="{{:MyUrl('index/user/reginfo')}}">{{:MyLang('common.register_title')}}</a>]
{{/if}}
{{else /}}
<em>{{:MyLang('common.header_top_nav_left_login_first')}}</em>
<em class="first">{{:MyLang('common.header_top_nav_left_login_first')}}</em>
{{if !empty($user['icon'])}}
<img src="{{$user.icon}}" class="common-user-icon" {{if !empty($user['icon_title'])}}title="{{$user.icon_title}}"{{/if}} />
{{/if}}
<em>{{$user.user_name_view}}{{:MyLang('common.header_top_nav_left_login_last')}}</em>
<em>{{:MyC('home_site_name')}}</em>
[<a href="{{:MyUrl('index/user/logout')}}">{{:MyLang('common.logout_title')}}</a>]
<em class="user">{{$user.user_name_view}}</em>
<em class="last">{{:MyLang('common.header_top_nav_left_login_last')}}</em>
<em class="site-name">{{:MyC('home_site_name')}}</em>
<em class="logout"><a href="{{:MyUrl('index/user/logout')}}">[{{:MyLang('common.logout_title')}}]</a></em>
{{/if}}
<!-- 公共顶部小导航钩子-左侧后面 -->
......@@ -109,7 +110,7 @@
<span>{{$nav.name}}</span>
<i class="am-icon-angle-down"></i>
</a>
<ul class="am-dropdown-content">
<ul class="am-dropdown-content am-radius">
{{foreach $nav.items as $navs}}
<li class="{{if ((isset($nav['is_login']) and $nav['is_login'] eq 1) or (isset($navs['is_login']) and $navs['is_login'] eq 1)) and empty($user)}}login-event{{/if}}">
<a href="{{if ((isset($nav['is_login']) and $nav['is_login'] eq 1) or (isset($navs['is_login']) and $navs['is_login'] eq 1)) and empty($user)}}javascript:;{{else /}}{{$navs.url}}{{/if}}">{{$navs.name}}</a>
......
......@@ -12,6 +12,7 @@ namespace app\install\controller;
use app\BaseController;
use app\service\SystemService;
use app\service\MultilingualService;
/**
* 安装程序-公共
......@@ -23,6 +24,9 @@ use app\service\SystemService;
*/
class Common extends BaseController
{
// 输入参数
protected $data_request;
/**
* 构造方法
* @author Devil
......@@ -33,29 +37,45 @@ class Common extends BaseController
*/
public function __construct()
{
// 输入参数
$this->data_request = input();
// 系统运行开始
SystemService::SystemBegin($this->data_request);
// 模板数据
$assign = [
// 当前方法
'action' => RequestAction(),
// 系统类型
'system_type' => SystemService::SystemTypeValue(),
// 系统环境参数最大数
'env_max_input_vars_count' => SystemService::EnvMaxInputVarsCount(),
// 默认不加载地图api、类型默认百度地图
'is_load_map_api' => 0,
'load_map_type' => MyC('common_map_type', 'baidu', true),
// 页面语言
'lang_data' => SystemService::PageViewLangData(),
// 多语言
'multilingual_default_code' => MultilingualService::GetUserMultilingualValue(),
];
// 模板赋值
MyViewAssign($assign);
}
/**
* 析构函数
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-03-18
* @desc description
*/
public function __destruct()
{
// 系统运行结束
SystemService::SystemEnd($this->data_request);
}
/**
* 空方法响应
* @author Devil
......
......@@ -433,6 +433,7 @@ return [
'loading_title' => 'Loading',
'lan_title' => 'Longitude',
'lat_title' => 'Latitude',
'lang_title' => 'Language',
// 商品基础相关
'goods_name' => 'Goods Name',
'goods_stop_sale_title' => 'Stop Sale',
......@@ -936,30 +937,30 @@ return [
],
// 时区
'site_timezone_list' => [
'Pacific/Pago_Pago' => '(Standard Time 11:00) Midway Island, Samoa',
'Pacific/Rarotonga' => '(Standard Time 10:00) Hawaii',
'Pacific/Gambier' => '(Standard Time 9:00) Alaska',
'America/Dawson' => '(Standard Time -8:00) Pacific Time (US and Canada)',
'America/Creston' => '(Standard Time -7:00) Mountain Time (US and Canada)',
'America/Belize' => '(Standard Time -6:00) Central Time (US and Canada), Mexico City',
'America/Eirunepe' => '(Standard Time -5:00) Eastern Time (United States and Canada), Bogota',
'America/Antigua' => '(Standard Time -4:00) Atlantic Time (Canada), Caracas',
'America/Argentina/Buenos_Aires' => '(Standard Time 3:00) Brazil, Buenos Aires, Georgetown',
'America/Noronha' => '(Standard Time 2:00) Mid-Atlantic',
'Atlantic/Cape_Verde' => '(Standard Time -1:00) Azores, Cape Verde',
'Africa/Ouagadougou' => '(Greenwich Mean Time) Western European Time, London, Casablanca',
'Europe/Andorra' => '(Standard Time +1:00) Central European Time, Angola, Libya',
'Europe/Mariehamn' => '(Standard Time +2:00) Eastern European Time, Cairo, Athens',
'Asia/Bahrain' => '(Standard Time +3:00) Baghdad, Kuwait, Moscow',
'Asia/Dubai' => '(Standard time +4:00) Abu Dhabi, Muscat, Baku',
'Asia/Kolkata' => '(Standard Time +5:00) Yekaterinburg, Islamabad, Karachi',
'Asia/Dhaka' => '(Standard Time +6:00) Almaty, Dhaka, New Siberia',
'Indian/Christmas' => '(Standard time +7:00) Bangkok, Hanoi, Jakarta',
'Asia/Shanghai' => '(Standard time +8:00) Beijing, Chongqing, Hong Kong, Singapore',
'Australia/Darwin' => '(Standard time +9:00) Tokyo, Seoul, Osaka, Yakutsk',
'Australia/Adelaide' => '(Standard Time +10:00) Sydney, Guam',
'Australia/Currie' => '(Standard time +11:00) Magadan, Solomon Islands',
'Pacific/Fiji' => '(Standard Time +12:00) Auckland, Wellington, Kamchatka Peninsula'
'Pacific/Pago_Pago' => '(Standard Time 11:00) Midway Island, Samoa',
'Pacific/Rarotonga' => '(Standard Time 10:00) Hawaii',
'Pacific/Gambier' => '(Standard Time 9:00) Alaska',
'America/Dawson' => '(Standard Time -8:00) Pacific Time (US and Canada)',
'America/Creston' => '(Standard Time -7:00) Mountain Time (US and Canada)',
'America/Belize' => '(Standard Time -6:00) Central Time (US and Canada), Mexico City',
'America/Eirunepe' => '(Standard Time -5:00) Eastern Time (United States and Canada), Bogota',
'America/Antigua' => '(Standard Time -4:00) Atlantic Time (Canada), Caracas',
'America/Argentina/Buenos_Aires' => '(Standard Time 3:00) Brazil, Buenos Aires, Georgetown',
'America/Noronha' => '(Standard Time 2:00) Mid-Atlantic',
'Atlantic/Cape_Verde' => '(Standard Time -1:00) Azores, Cape Verde',
'Africa/Ouagadougou' => '(Greenwich Mean Time) Western European Time, London, Casablanca',
'Europe/Andorra' => '(Standard Time +1:00) Central European Time, Angola, Libya',
'Europe/Mariehamn' => '(Standard Time +2:00) Eastern European Time, Cairo, Athens',
'Asia/Bahrain' => '(Standard Time +3:00) Baghdad, Kuwait, Moscow',
'Asia/Dubai' => '(Standard time +4:00) Abu Dhabi, Muscat, Baku',
'Asia/Kolkata' => '(Standard Time +5:00) Yekaterinburg, Islamabad, Karachi',
'Asia/Dhaka' => '(Standard Time +6:00) Almaty, Dhaka, New Siberia',
'Indian/Christmas' => '(Standard time +7:00) Bangkok, Hanoi, Jakarta',
'Asia/Shanghai' => '(Standard time +8:00) Beijing, Chongqing, Hong Kong, Singapore',
'Australia/Darwin' => '(Standard time +9:00) Tokyo, Seoul, Osaka, Yakutsk',
'Australia/Adelaide' => '(Standard Time +10:00) Sydney, Guam',
'Australia/Currie' => '(Standard time +11:00) Magadan, Solomon Islands',
'Pacific/Fiji' => '(Standard Time +12:00) Auckland, Wellington, Kamchatka Peninsula'
],
// seo
// url模式列表
......@@ -969,6 +970,24 @@ return [
2 => ['value' => 2, 'name' => 'PATHINFO Mode+ShortAddress'],
],
// 多语言(preg 正则匹配、code 语言编码、name 语言名称)
'common_multilingual_list' => [
'zh' => 'Simplified Chinese',
'cht' => 'Traditional Chinese',
'en' => 'English',
'ru' => 'Russian',
'kor' => 'Korean',
'th' => 'Thai',
'jp' => 'Japanese',
'de' => 'German',
'nl' => 'Dutch',
'vie' => 'Vietnamese',
'it' => 'Italian',
'spa' => 'Spanish',
'fra' => 'French',
'swe' => 'Swedish',
],
// -------------------- 公共服务层 --------------------
'common_service' => [
// 权限管理
......@@ -1329,7 +1348,7 @@ return [
'form_item_name_message' => 'Name format 2~30 characters',
'form_item_category_id' => 'Goods Category',
'form_item_category_id_tips' => 'Include children',
'form_item_category_id_message' => 'Please select product classification',
'form_item_category_id_message' => 'Please select goods classification',
'form_item_config_title' => 'Params Config',
'form_item_config_value_placeholder' => 'Paste goods parameter configuration information',
'form_item_config_template_title' => 'Goods Params template',
......@@ -1350,7 +1369,7 @@ return [
'form_item_name_message' => 'Name format 1~30 characters',
'form_item_category_id' => 'Goods Category',
'form_item_category_id_tips' => 'Include children',
'form_item_category_id_message' => 'Please select product classification',
'form_item_category_id_message' => 'Please select goods classification',
'form_item_content' => 'Spec Value',
'form_item_content_placeholder' => 'Specification value (multiple values can be achieved by entering Enter)',
'form_item_content_message' => 'Specification value format: 1~1000 characters',
......@@ -1394,7 +1413,7 @@ return [
'form_item_site_type_tips' => [
'1. The currently configured site type is ( 站点类型 )',
'2. If the goods type is not configured, follow the site type configured by the system',
'3. When the set goods type is not included in the site type set by the system, the function of adding products to the shopping cart will be invalid',
'3. When the set goods type is not included in the site type set by the system, the function of adding goods to the shopping cart will be invalid',
],
'form_item_site_type_message' => 'Please select goods type',
'form_item_images' => 'cover photo',
......@@ -1413,7 +1432,7 @@ return [
'form_spec_template_tips' => 'Incorrect specification template data',
'form_spec_template_name_exist_tips' => 'The same specification name already exists',
'form_spec_template_placeholder' => 'Goods specification template...',
'form_spec_template_message' => 'Please select a product specification template',
'form_spec_template_message' => 'Please select a goods specification template',
'form_spec_quick_add_title' => 'Batch add specifications',
'form_spec_quick_generate_title' => 'Generate specifications',
'form_spec_type_title' => 'Spec Name',
......@@ -1460,7 +1479,7 @@ return [
// 参数
'form_params_select_title' => 'Goods Params Template',
'form_params_select_placeholder' => 'Goods Params Template...',
'form_params_select_message' => 'Please select a product parameter template',
'form_params_select_message' => 'Please select a goods parameter template',
'form_params_value_placeholder' => 'Paste goods parameter configuration information',
'form_params_config_copy_title' => 'Copy Config',
'form_params_config_empty_title' => 'Clear Params',
......@@ -1764,7 +1783,7 @@ return [
'order_under_line_name' => 'Offline payment',
'order_item_summary_desc' => '共{:buy_number_count}件 合计:{:currency_symbol}{:total_price}元',
'order_goods_sales_count_inc_fail_tips' => 'Failed to increase sales volume of order goods',
'order_detail_goods_empty_tips' => 'There is an error in the order. No related products were found',
'order_detail_goods_empty_tips' => 'There is an error in the order. No related goods were found',
'pay_have_in_hand_tips' => 'In payment',
// 取消
'order_cancel_message_data' => [
......@@ -2762,7 +2781,7 @@ return [
'tips' => '',
],
'common_spec_add_max_number' => [
'name' => 'Maximum quantity of product specifications that can be added',
'name' => 'Maximum quantity of goods specifications that can be added',
'desc' => 'No more than 3 specifications are recommended',
'tips' => 'Please fill in the maximum number of Google',
],
......@@ -2994,7 +3013,7 @@ return [
'common_goods_give_integral_limit_time' => [
'name' => 'Credit duration of goods',
'desc' => 'Unit minute, 21600 minutes/15 days by default',
'tips' => 'Please fill in the time length of product gift points',
'tips' => 'Please fill in the time length of goods gift points',
],
'common_app_mini_baidu_appid' => [
'name' => 'AppID',
......@@ -3129,7 +3148,7 @@ return [
'common_is_goods_detail_show_photo' => [
'name' => 'Product detail page display album',
'desc' => 'Default no',
'tips' => 'Please select whether to display the album on the product details page',
'tips' => 'Please select whether to display the album on the goods details page',
],
'common_is_mobile_concise_model' => [
'name' => 'Mobile phone simple mode',
......@@ -3342,9 +3361,9 @@ return [
'tips' => 'Please select https for the connection store',
],
'is_close_goods_discount_overlap' => [
'name' => 'Close the product discount overlap',
'name' => 'Close the goods discount overlap',
'desc' => 'Default no',
'tips' => 'Please select to close the product discount overlap',
'tips' => 'Please select to close the goods discount overlap',
],
'home_theme_footer_bottom_powered' => [
'name' => 'Copyright information at the bottom of the web',
......@@ -3397,9 +3416,9 @@ return [
'tips' => 'Please select the order item sales increase rule',
],
'common_is_show_goods_comments' => [
'name' => 'Show product evaluation',
'name' => 'Show goods evaluation',
'desc' => 'Default is',
'tips' => 'Please select whether to display product evaluation',
'tips' => 'Please select whether to display goods evaluation',
],
'common_app_h5_url' => [
'name' => 'Mobile terminal h5 address',
......
......@@ -434,6 +434,7 @@ return [
'loading_title' => '加载',
'lan_title' => '经度',
'lat_title' => '纬度',
'lang_title' => '语言',
// 商品基础相关
'goods_name' => '商品名称',
'goods_stop_sale_title' => '暂停销售',
......@@ -937,30 +938,30 @@ return [
],
// 时区
'site_timezone_list' => [
'Pacific/Pago_Pago' => '(标准时-11:00) 中途岛、萨摩亚群岛',
'Pacific/Rarotonga' => '(标准时-10:00) 夏威夷',
'Pacific/Gambier' => '(标准时-9:00) 阿拉斯加',
'America/Dawson' => '(标准时-8:00) 太平洋时间(美国和加拿大)',
'America/Creston' => '(标准时-7:00) 山地时间(美国和加拿大)',
'America/Belize' => '(标准时-6:00) 中部时间(美国和加拿大)、墨西哥城',
'America/Eirunepe' => '(标准时-5:00) 东部时间(美国和加拿大)、波哥大',
'America/Antigua' => '(标准时-4:00) 大西洋时间(加拿大)、加拉加斯',
'America/Argentina/Buenos_Aires' => '(标准时-3:00) 巴西、布宜诺斯艾利斯、乔治敦',
'America/Noronha' => '(标准时-2:00) 中大西洋',
'Atlantic/Cape_Verde' => '(标准时-1:00) 亚速尔群岛、佛得角群岛',
'Africa/Ouagadougou' => '(格林尼治标准时) 西欧时间、伦敦、卡萨布兰卡',
'Europe/Andorra' => '(标准时+1:00) 中欧时间、安哥拉、利比亚',
'Europe/Mariehamn' => '(标准时+2:00) 东欧时间、开罗,雅典',
'Asia/Bahrain' => '(标准时+3:00) 巴格达、科威特、莫斯科',
'Asia/Dubai' => '(标准时+4:00) 阿布扎比、马斯喀特、巴库',
'Asia/Kolkata' => '(标准时+5:00) 叶卡捷琳堡、伊斯兰堡、卡拉奇',
'Asia/Dhaka' => '(标准时+6:00) 阿拉木图、 达卡、新亚伯利亚',
'Indian/Christmas' => '(标准时+7:00) 曼谷、河内、雅加达',
'Asia/Shanghai' => '(标准时+8:00)北京、重庆、香港、新加坡',
'Australia/Darwin' => '(标准时+9:00) 东京、汉城、大阪、雅库茨克',
'Australia/Adelaide' => '(标准时+10:00) 悉尼、关岛',
'Australia/Currie' => '(标准时+11:00) 马加丹、索罗门群岛',
'Pacific/Fiji' => '(标准时+12:00) 奥克兰、惠灵顿、堪察加半岛'
'Pacific/Pago_Pago' => '(标准时-11:00) 中途岛、萨摩亚群岛',
'Pacific/Rarotonga' => '(标准时-10:00) 夏威夷',
'Pacific/Gambier' => '(标准时-9:00) 阿拉斯加',
'America/Dawson' => '(标准时-8:00) 太平洋时间(美国和加拿大)',
'America/Creston' => '(标准时-7:00) 山地时间(美国和加拿大)',
'America/Belize' => '(标准时-6:00) 中部时间(美国和加拿大)、墨西哥城',
'America/Eirunepe' => '(标准时-5:00) 东部时间(美国和加拿大)、波哥大',
'America/Antigua' => '(标准时-4:00) 大西洋时间(加拿大)、加拉加斯',
'America/Argentina/Buenos_Aires' => '(标准时-3:00) 巴西、布宜诺斯艾利斯、乔治敦',
'America/Noronha' => '(标准时-2:00) 中大西洋',
'Atlantic/Cape_Verde' => '(标准时-1:00) 亚速尔群岛、佛得角群岛',
'Africa/Ouagadougou' => '(格林尼治标准时) 西欧时间、伦敦、卡萨布兰卡',
'Europe/Andorra' => '(标准时+1:00) 中欧时间、安哥拉、利比亚',
'Europe/Mariehamn' => '(标准时+2:00) 东欧时间、开罗,雅典',
'Asia/Bahrain' => '(标准时+3:00) 巴格达、科威特、莫斯科',
'Asia/Dubai' => '(标准时+4:00) 阿布扎比、马斯喀特、巴库',
'Asia/Kolkata' => '(标准时+5:00) 叶卡捷琳堡、伊斯兰堡、卡拉奇',
'Asia/Dhaka' => '(标准时+6:00) 阿拉木图、 达卡、新亚伯利亚',
'Indian/Christmas' => '(标准时+7:00) 曼谷、河内、雅加达',
'Asia/Shanghai' => '(标准时+8:00)北京、重庆、香港、新加坡',
'Australia/Darwin' => '(标准时+9:00) 东京、汉城、大阪、雅库茨克',
'Australia/Adelaide' => '(标准时+10:00) 悉尼、关岛',
'Australia/Currie' => '(标准时+11:00) 马加丹、索罗门群岛',
'Pacific/Fiji' => '(标准时+12:00) 奥克兰、惠灵顿、堪察加半岛'
],
// seo
// url模式列表
......@@ -970,6 +971,24 @@ return [
2 => ['value' => 2, 'name' => 'PATHINFO模式+短地址'],
],
// 多语言code 语言编码 => name 语言名称)
'common_multilingual_list' => [
'zh' => '简体中文',
'cht' => '繁体中文',
'en' => '英文',
'ru' => '俄语',
'kor' => '韩语',
'th' => '泰语',
'jp' => '日语',
'de' => '德语',
'nl' => '荷兰语',
'vie' => '越南语',
'it' => '意大利语',
'spa' => '西班牙语',
'fra' => '法语',
'swe' => '瑞典语',
],
// -------------------- 公共服务层 --------------------
'common_service' => [
// 权限管理
......
......@@ -14,7 +14,7 @@ return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
\think\middleware\LoadLangPack::class,
// \think\middleware\LoadLangPack::class,
// Session初始化
\think\middleware\SessionInit::class
];
......
<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2099 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/mit-license.php )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace app\service;
use app\service\UserService;
use app\service\AdminService;
/**
* 多语言服务层
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-01T21:51:08+0800
*/
class MultilingualService
{
// 多语言选择缓存key
public static $cache_key = 'multilingual_language';
/**
* 获取当前默认语言信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2023-02-13
* @desc description
*/
public static function MultilingualData()
{
static $user_multilingual_result = [];
if(empty($user_multilingual_result))
{
$default = [];
$select = [];
$allow_lang_list = MyConfig('lang.allow_lang_list');
$multilingual_list = MyLang('common_multilingual_list');
if(!empty($multilingual_list) && is_array($multilingual_list) && !empty($allow_lang_list) && is_array($allow_lang_list))
{
$allow_lang_list = array_column($allow_lang_list, null, 'code');
$user_lang = self::GetUserMultilingualValue();
$default_lang = MyConfig('lang.default_lang');
$url = self::CurrentViewUrl();
foreach($multilingual_list as $k=>$v)
{
if(array_key_exists($k, $allow_lang_list) || $k == $default_lang)
{
// 加入语言名称
$temp = array_merge($allow_lang_list[$k], [
'name' =>$v,
'url' =>$url.$k,
]);
// 可选语言
$select[] = $temp;
// 默认语言
if(empty($default) && !empty($default_lang) && $k == $default_lang)
{
$default = $temp;
}
// 当前选择的语言
if(!empty($user_lang) && $k == $user_lang)
{
$default = $temp;
}
}
}
// 未匹配到则使用第一个
if(empty($default) && !empty($select))
{
$default = $select[0];
}
}
$user_multilingual_result = [
'default' => $default,
'data' => $select,
];
}
return $user_multilingual_result;
}
/**
* 当前页面url地址
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2023-02-13
* @desc description
*/
public static function CurrentViewUrl()
{
// 去除当前存在的参数
$url = __MY_VIEW_URL__;
$lang_var = MyConfig('lang.detect_var');
if(stripos($url, $lang_var) !== false)
{
$arr1 = explode('?', $url);
if(!empty($arr1[1]))
{
$arr2 = explode('&', $arr1[1]);
foreach($arr2 as $k=>$v)
{
if(stripos($v, $lang_var) !== false)
{
unset($arr2[$k]);
}
}
$url = '?'.implode('&', $arr2);
}
}
// 当前页面地址
$join = (stripos($url, '?') === false) ? '?' : '&';
return $url.$join.$lang_var.'=';
}
/**
* 当前语言
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-09-10
* @desc description
*/
public static function GetUserMultilingualValue()
{
static $user_multilingual_value = null;
if(is_null($user_multilingual_value))
{
// 参数指定
$value = input(MyConfig('lang.detect_var'));
// 请求头
if(empty($value))
{
$header_var = MyConfig('lang.header_var');
if(!empty($_SERVER[$header_var]))
{
$value = strtolower($_SERVER[$header_var]);
}
}
// cookie
if(empty($value))
{
$value = MyCookie(MyConfig('lang.cookie_var'));
}
// session读取
if(empty($value))
{
$value = MySession(self::CacheKey(self::$cache_key));
}
// 根据uuid读取
if(empty($value))
{
$uuid = input('uuid');
if(!empty($uuid))
{
$value = MyCache(self::CacheKey(self::$cache_key.'_'.$uuid));
}
}
// 根据用户读取
if(empty($value))
{
$user = (RequestModule() == 'admin') ? AdminService::LoginInfo() : UserService::LoginUserInfo();
if(!empty($user['id']))
{
// 缓存读取
$value = MyCache(self::CacheKey(self::$cache_key.'_'.$user['id']));
}
}
// 自动检测
if(empty($value))
{
$value = self::BrowserHttpAcceptLanguage();
}
// 默认语言
if(empty($value))
{
$value = MyConfig('lang.default_lang');
}
$user_multilingual_value = $value;
}
return $user_multilingual_value;
}
/**
* 设置用户选择的语言
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-09-10
* @desc description
*/
public static function SetUserMultilingualValue()
{
$value = input(MyConfig('lang.detect_var'));
if(!empty($value))
{
// session
MySession(self::CacheKey(self::$cache_key), $value);
// 当前用户
$user = UserService::LoginUserInfo();
if(!empty($user['id']))
{
MyCache(self::CacheKey(self::$cache_key.'_'.$user['id']), $value);
}
// uuid
$uuid = input('uuid');
if(!empty($uuid))
{
MyCache(self::CacheKey(self::$cache_key.'_'.$uuid), $value);
}
}
return true;
}
/**
* 缓存key
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-05-14
* @desc description
* @param [string] $key [缓存key]
*/
public static function CacheKey($key)
{
return RequestModule().'_'.$key;
}
/**
* 获取浏览器默认语言
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-08-22
* @desc description
*/
public static function BrowserHttpAcceptLanguage()
{
$value = '';
if(!empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
$lang_list = MyConfig('lang.allow_lang_list');
if(!empty($lang_list) && is_array($lang_list))
{
//只取前4位,这样只判断最优先的语言。如果取前5位,可能出现en,zh的情况,影响判断。
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 4);
foreach($lang_list as $v)
{
if(!empty($v['preg']) && preg_match('/'.$v['preg'].'/i', $lang))
{
$value = $v['code'];
break;
}
}
}
}
return $value;
}
}
?>
\ No newline at end of file
......@@ -608,7 +608,7 @@ class NavigationService
$key = SystemService::CacheKey('shopxo.cache_header_navigation_top_right_key');
$data = MyCache($key);
if($data === null || MyEnv('app_debug'))
{
{
// 列表
$lang = MyLang('common_service.navigation.header_top_nav_right');
$data = [
......@@ -669,6 +669,20 @@ class NavigationService
],
];
// 追加多语言
$multilingual_data = MultilingualService::MultilingualData();
if(!empty($multilingual_data) && !empty($multilingual_data['data']) && !empty($multilingual_data['default']))
{
$data[] = [
'name' => MyLang('lang_title').'['.$multilingual_data['default']['name'].']',
'is_login' => 0,
'badge' => null,
'icon' => 'am-icon-language',
'url' => '',
'items' => $multilingual_data['data'],
];
}
// 顶部小导航右侧钩子
$hook_name = 'plugins_service_header_navigation_top_right_handle';
MyEventTrigger($hook_name, [
......
......@@ -11,6 +11,7 @@
namespace app\service;
use app\service\UserService;
use app\service\MultilingualService;
/**
* 配置服务层
......@@ -97,6 +98,9 @@ class SystemService
MySession('share_referrer_id', $params['referrer']);
MyCookie('share_referrer_id', $params['referrer'], false);
}
// 多语言初始化设置
MultilingualService::SetUserMultilingualValue();
}
/**
......@@ -214,6 +218,9 @@ class SystemService
}
$data = array_merge($lang_common, $lang_page);
// 追加多语言code
$data['multilingual_default_code'] = MultilingualService::GetUserMultilingualValue();
// 页面语言读取钩子
$hook_name = 'plugins_page_view_lang_data';
MyEventTrigger($hook_name,
......
......@@ -14,23 +14,50 @@
// +----------------------------------------------------------------------
return [
// 默认语言
'default_lang' => 'en-us',
// 允许的语言列表
'allow_lang_list' => [],
// 多语言自动侦测变量名
'default_lang' => 'zh',
// 允许的语言列表(preg 正则匹配、code 语言编码、语言名称在对应语言文件中)
'allow_lang_list' => [
// 简体中文
['preg' => 'zh-c', 'code' => 'zh'],
// 繁体中文
['preg' => 'zh-t', 'code' => 'cht'],
// 英文
['preg' => 'en', 'code' => 'en'],
// 俄语
['preg' => 'rn', 'code' => 'ru'],
// 韩语
['preg' => 'ko', 'code' => 'kor'],
// 泰语
['preg' => 'th', 'code' => 'th'],
// 日语
['preg' => 'jp', 'code' => 'jp'],
// 德语
['preg' => 'de', 'code' => 'de'],
// 荷兰语
['preg' => 'nl', 'code' => 'nl'],
// 越南语
['preg' => 'vi', 'code' => 'vie'],
// 意大利语
['preg' => 'it', 'code' => 'it'],
// 西班牙语
['preg' => 'es', 'code' => 'spa'],
// 法语
['preg' => 'fr', 'code' => 'fra'],
// 瑞典语
['preg' => 'sv', 'code' => 'swe'],
],
// 多语言url请求自动侦测变量名
'detect_var' => 'lang',
// 是否使用Cookie记录
'use_cookie' => true,
// 多语言cookie变量
'cookie_var' => 'think_lang',
'cookie_var' => 'lang',
// 多语言header变量
'header_var' => 'think-lang',
'header_var' => 'lang',
// 扩展语言包
'extend_list' => [],
// Accept-Language转义为对应语言包名称
'accept_language' => [
'zh-hans-cn' => 'zh-cn',
],
'accept_language' => [],
// 是否支持语言分组
'allow_group' => false,
];
......
......@@ -66,7 +66,7 @@
* 导航打开页面列表
*/
.header-menu-open-pages-list {
max-width: calc(100% - 650px);
max-width: calc(100% - 750px);
margin-top: 4px;
margin-left: 20px;
height: 25px;
......
......@@ -87,7 +87,7 @@ input.add,input.min{width:15px}
.mui-mbar-tabs{ display:none;}
/* 顶部小导航 */
.header-top { background-color: #fafafa; border-bottom: solid 1px #f0f0f0; height: 30px; display:none; }
.header-top { background-color: #fafafa; border-bottom: solid 1px #f0f0f0; height: 30px; line-height: 30px; }
.header{ max-width:1000px; margin:0px auto; font-size:12px;position: relative; }
.mobile-navigation{position: fixed;bottom:0px ;width: 100%;z-index: 999;background:#fff ;}
......@@ -100,7 +100,6 @@ input.add,input.min{width:15px}
@media only screen and (min-width: 641px) {
.am-container {padding-left:0px;padding-right:0px ;}
.nav-search{background: #fff; margin: 20px 0 5px 0;}
.header-top { display:block;}
.top-nav-left{ float:left;}
.top-nav-left .top-nav-items, .top-nav-right .top-nav-items { padding: 0px 8px; height: 30px; line-height: 30px; }
.top-nav-right {position: absolute; top: 0; right: 0; }
......@@ -181,8 +180,6 @@ input.add,input.min{width:15px}
#goods-category .category-content { opacity: 0.8; -webkit-transition: opacity .2s ease-in; -moz-transition: opacity .2s ease-in; -ms-transition: opacity .2s ease-in; -o-transition: opacity .2s ease-in; transition: opacity .2s ease-in; }
#goods-category:hover .category-content { opacity: 1; }
}
@media only screen and (min-width: 1260px) {
.am-container, .footer, .nav-table {padding-left:0rem;padding-right:0rem;max-width: 1200px;}
.footer{margin: auto;}
......@@ -201,6 +198,18 @@ input.add,input.min{width:15px}
.category-content .category-name i { top:6px; }
.category-content .category-info em{ top:9px; }
}
@media only screen and (max-width: 640px) {
.header-top { background: #d2354c; border-bottom-color: #cb2f46; padding: 0 10px; }
.header-top * {color: #ececec;}
.header-top .top-nav-items,
.top-nav-left { float: left; }
.top-nav-right { float: right; }
.top-nav-right .top-nav-items:not(:last-child) { margin-right: 12px; }
.top-nav-right .top-nav-items a span,
.header-top .top-nav-left .menu-hd .last,
.header-top .top-nav-left .menu-hd .site-name,
.header-top .top-nav-left .menu-hd .logout { display: none; }
}
/**
* 公共
......@@ -825,7 +834,7 @@ table.am-table .am-dropdown.am-active .am-selected-btn.am-btn-default.am-dropdow
.shop-navigation .wap-logo {
max-width: 100px;
max-height: 45px;
padding: 5px;
padding: 5px 5px 5px 10px;
line-height: 30px;
}
.shop-navigation .wap-logo img {
......@@ -1168,4 +1177,11 @@ legend a.am-fr {
*/
.table-three-nav li.am-active > a {
background-color: #eee !important;
}
/**
* 动态数据列表
*/
.am-table-scrollable-horizontal .am-table tr .am-operate-grid {
min-width: 120px;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册