diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 132d653e..3ff06d1f 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -12,6 +12,7 @@ use App\Models\Player; use App\Models\Texture; use Illuminate\Support\Arr; use Illuminate\Http\Request; +use App\Services\OptionForm; use App\Exceptions\PrettyPageException; use App\Services\Repositories\UserRepository; @@ -32,70 +33,69 @@ class AdminController extends Controller $color_scheme = str_replace('_', '-', $request->input('color_scheme')); option(['color_scheme' => $color_scheme]); - return json('修改配色成功', 0); + return json(trans('admin.customize.change-color.success'), 0); } - $homepage = Option::form('homepage', '首页配置', function($form) + $homepage = Option::form('homepage', OptionForm::AUTO_DETECT, function($form) { - $form->text('home_pic_url', '首页图片地址')->hint('相对于首页的路径或者完整的 URL'); + $form->text('home_pic_url')->hint(OptionForm::AUTO_DETECT); - $form->text('favicon_url', '网站图标')->hint('相对 resources/assets/ 的路径或者完整的 URL') - ->description('所使用的图像必须具有相同的宽度和高度'); + $form->text('favicon_url')->hint(OptionForm::AUTO_DETECT) + ->description(OptionForm::AUTO_DETECT); - $form->select('copyright_prefer', '程序版权信息') + $form->select('copyright_prefer') ->option('0', 'Powered with ❤ by Blessing Skin Server.') ->option('1', 'Powered by Blessing Skin Server.') - ->option('2', '由 Blessing Skin Server 强力驱动.') - ->option('3', '自豪地采用 Blessing Skin Server.') - ->description('对于任何恶意修改页面右下角的版权信息(包括不限于删除、修改作者信息、修改链接指向)的用户,作者保留对其追究责任的权力。'); + ->option('2', 'Proudly powered by Blessing Skin Server.') + ->option('3', '由 Blessing Skin Server 强力驱动.') + ->option('4', '自豪地采用 Blessing Skin Server.') + ->description(OptionForm::AUTO_DETECT); - $form->textarea('copyright_text', '自定义版权文字')->rows(6) - ->description('自定义版权文字内可使用占位符,{site_name} 将会被自动替换为站点名称,{site_url} 会被替换为站点地址。'); + $form->textarea('copyright_text')->rows(6) + ->description(OptionForm::AUTO_DETECT); })->handle(); - $customJsCss = Option::form('customJsCss', '自定义 CSS/JavaScript', function($form) + $customJsCss = Option::form('customJsCss', OptionForm::AUTO_DETECT, function($form) { $form->textarea('custom_css', 'CSS')->rows(6); $form->textarea('custom_js', 'JavaScript')->rows(6); - })->addMessage(' - 内容将会被追加至每个页面的 <style> 和 <script> 标签中。
- - 这里有一些有用的示例:「自定义 CSS JavaScript」功能的一些实例@GitHub WiKi - ')->handle(); + })->addMessage(OptionForm::AUTO_DETECT)->handle(); return view('admin.customize', ['forms' => compact('homepage', 'customJsCss')]); } public function score() { - $rate = Option::form('rate', '积分换算', function($form) + $rate = Option::form('rate', OptionForm::AUTO_DETECT, function($form) { - $form->group('score_per_storage', '存储')->text('score_per_storage')->addon('积分 = 1 KB'); + $form->group('score_per_storage')->text('score_per_storage')->addon(OptionForm::AUTO_DETECT); - $form->group('private_score_per_storage', '私密材质存储') - ->text('private_score_per_storage')->addon('积分 = 1 KB') - ->hint('上传私密材质将消耗更多积分'); + $form->group('private_score_per_storage') + ->text('private_score_per_storage')->addon(OptionForm::AUTO_DETECT) + ->hint(OptionForm::AUTO_DETECT); - $form->group('score_per_closet_item', '收藏消耗积分') - ->text('score_per_closet_item')->addon('积分 = 一个衣柜物品'); + $form->group('score_per_closet_item') + ->text('score_per_closet_item')->addon(OptionForm::AUTO_DETECT); - $form->checkbox('return_score', '积分返还')->label('用户删除角色/材质/收藏时返还积分'); + $form->checkbox('return_score')->label(OptionForm::AUTO_DETECT); - $form->group('score_per_player', '角色')->text('score_per_player')->addon('积分 = 一个角色'); + $form->group('score_per_player')->text('score_per_player')->addon(OptionForm::AUTO_DETECT); - $form->text('user_initial_score', '新用户默认积分'); + $form->text('user_initial_score'); })->handle(); - $signIn = Option::form('sign_in', '签到配置', function($form) + $signIn = Option::form('sign_in', OptionForm::AUTO_DETECT, function($form) { - $form->group('sign_score', '签到获得积分') - ->text('sign_score_from')->addon('积分 ~ ')->text('sign_score_to')->addon('积分'); + $form->group('sign_score') + ->text('sign_score_from')->addon(trans('options.sign_score.addon1')) + ->text('sign_score_to')->addon(trans('options.sign_score.addon2')); - $form->group('sign_gap_time', '签到间隔时间')->text('sign_gap_time')->addon('小时'); + $form->group('sign_gap_time')->text('sign_gap_time')->addon(OptionForm::AUTO_DETECT); - $form->checkbox('sign_after_zero', '签到时间')->label('每天零点后可签到') - ->hint('勾选后将无视上一条,每天零时后均可签到'); + $form->checkbox('sign_after_zero')->label(OptionForm::AUTO_DETECT) + ->hint(OptionForm::AUTO_DETECT); })->handle(function() { $sign_score = $_POST['sign_score_from'].','.$_POST['sign_score_to']; Option::set('sign_score', $sign_score); @@ -112,52 +112,52 @@ class AdminController extends Controller public function options() { - $general = Option::form('general', '常规选项', function($form) + $general = Option::form('general', OptionForm::AUTO_DETECT, function($form) { - $form->text('site_name', '站点标题'); - $form->text('site_description', '站点描述'); - $form->text('site_url', '站点地址(URL)')->hint('以 http(s):// 开头,不要以 / 结尾'); + $form->text('site_name'); + $form->text('site_description'); + $form->text('site_url')->hint(OptionForm::AUTO_DETECT); - $form->checkbox('user_can_register', '开放注册')->label('任何人都可以注册'); + $form->checkbox('user_can_register')->label(OptionForm::AUTO_DETECT); - $form->text('regs_per_ip', '每个 IP 限制注册数'); + $form->text('regs_per_ip'); - $form->group('max_upload_file_size', '最大允许上传大小') + $form->group('max_upload_file_size') ->text('max_upload_file_size')->addon('KB') - ->hint('PHP 限制:'.ini_get('upload_max_filesize').',定义在 php.ini 中。'); + ->hint(trans('options.max_upload_file_size.hint', ['size' => ini_get('upload_max_filesize')])); - $form->checkbox('allow_chinese_playername', '角色名')->label('允许中文角色名'); + $form->checkbox('allow_chinese_playername')->label(OptionForm::AUTO_DETECT); - $form->select('api_type', '首选 JSON API') + $form->select('api_type') ->option('0', 'CustomSkinLoader API') ->option('1', 'UniversalSkinAPI'); - $form->checkbox('auto_del_invalid_texture', '失效材质')->label('自动删除失效材质')->hint('自动从皮肤库中删除文件不存在的材质记录'); + $form->checkbox('auto_del_invalid_texture')->label(OptionForm::AUTO_DETECT)->hint(OptionForm::AUTO_DETECT); - $form->textarea('comment_script', '评论代码')->rows(6)->description('评论代码内可使用占位符,{tid} 将会被自动替换为材质的 id,{name} 会被替换为材质名称,{url} 会被替换为当前页面地址。'); + $form->textarea('comment_script')->rows(6)->description(OptionForm::AUTO_DETECT); })->handle(function() { if (substr($_POST['site_url'], -1) == "/") $_POST['site_url'] = substr($_POST['site_url'], 0, -1); }); - $announcement = Option::form('announcement', '站点公告', function($form) + $announ = Option::form('announ', OptionForm::AUTO_DETECT, function($form) { - $form->textarea('announcement')->description('可使用 Markdown 进行排版'); + $form->textarea('announcement')->description(OptionForm::AUTO_DETECT); })->renderWithOutTable()->handle(); - $cache = Option::form('cache', '资源文件配置', function($form) + $cache = Option::form('cache', OptionForm::AUTO_DETECT, function($form) { - $form->checkbox('force_ssl', '强制 SSL')->label('强制使用 HTTPS 协议加载资源')->hint('请确认 SSL 可用后再开启'); - $form->checkbox('auto_detect_asset_url', '资源地址')->label('自动判断资源文件地址')->hint('根据当前 URL 自动加载资源文件,如果关闭则将根据「站点地址」填写的内容加载。如果出现 CDN 回源问题请关闭'); - $form->checkbox('return_200_when_notfound', 'HTTP 响应码')->label('请求不存在的角色时返回 200 而不是 404'); + $form->checkbox('force_ssl')->label(OptionForm::AUTO_DETECT)->hint(OptionForm::AUTO_DETECT); + $form->checkbox('auto_detect_asset_url')->label(OptionForm::AUTO_DETECT)->description(OptionForm::AUTO_DETECT); + $form->checkbox('return_200_when_notfound')->label(OptionForm::AUTO_DETECT); - $form->text('cache_expire_time', '缓存失效时间')->hint('秒数,86400 = 一天,31536000 = 一年'); + $form->text('cache_expire_time')->hint(OptionForm::AUTO_DETECT); - })->type('warning')->hint('如果启用了 CDN 缓存请适当修改这些配置')->handle(); + })->type('warning')->hint(OptionForm::AUTO_DETECT)->handle(); - return view('admin.options')->with('forms', compact('general', 'cache', 'announcement')); + return view('admin.options')->with('forms', compact('general', 'cache', 'announ')); } /** diff --git a/app/Services/OptionForm.php b/app/Services/OptionForm.php index 824ad96b..d1133af2 100644 --- a/app/Services/OptionForm.php +++ b/app/Services/OptionForm.php @@ -10,6 +10,12 @@ use BadMethodCallException; class OptionForm { + /** + * Pass this value to tell generator to + * load text from language files automatically. + */ + const AUTO_DETECT = 0x97ab1; + protected $id; protected $title; @@ -37,28 +43,37 @@ class OptionForm */ public function __construct($id, $title) { - $this->id = $id; - $this->title = $title; + $this->id = $id; + + if ($title == self::AUTO_DETECT) { + $this->title = trans("options.$this->id.title"); + } else { + $this->title = $title; + } } /** * Add option item to the form dynamically. * * @param string $method - * @param array $parameters + * @param array $params * @return OptionItem * * @throws \BadMethodCallException */ - public function __call($method, $parameters) + public function __call($method, $params) { if (!in_array($method, ['text', 'checkbox', 'textarea', 'select', 'group'])) { throw new BadMethodCallException("Method [$method] does not exist on option form."); } + if (!isset($params[1]) || Arr::get($params, 1) == OptionForm::AUTO_DETECT) { + $params[1] = Arr::get(trans("options.$params[0]"), 'title', trans("options.$params[0]")); + } + $class = new ReflectionClass('App\Services\OptionForm'.Str::title($method)); // use ReflectionClass to create a new OptionFormItem instance - $item = $class->newInstanceArgs($parameters); + $item = $class->newInstanceArgs($params); $this->items[] = $item; return $item; @@ -85,6 +100,10 @@ class OptionForm */ public function hint($hintContent) { + if ($hintContent == self::AUTO_DETECT) { + $hintContent = trans("options.$this->id.hint"); + } + $this->hint = view('vendor.option-form.hint')->with('hint', $hintContent)->render(); return $this; @@ -145,6 +164,10 @@ class OptionForm */ public function addMessage($msg, $style = "info") { + if ($msg == self::AUTO_DETECT) { + $msg = trans("options.$this->id.message"); + } + $this->messages[] = "
$msg
"; return $this; @@ -236,7 +259,7 @@ class OptionForm Option::set($key, serialize($value)); } - $this->addMessage('设置已保存。', 'success'); + $this->addMessage(trans('options.option-saved'), 'success'); } return $this; @@ -375,6 +398,10 @@ class OptionFormItem public function hint($hintContent) { + if ($hintContent == OptionForm::AUTO_DETECT) { + $hintContent = trans("options.$this->id.hint"); + } + $this->hint = view('vendor.option-form.hint')->with('hint', $hintContent)->render(); return $this; @@ -389,6 +416,10 @@ class OptionFormItem public function description($description) { + if ($description == OptionForm::AUTO_DETECT) { + $description = trans("options.$this->id.description"); + } + $this->description = $description; return $this; @@ -424,6 +455,10 @@ class OptionFormCheckbox extends OptionFormItem public function label($label) { + if ($label == OptionForm::AUTO_DETECT) { + $label = trans("options.$this->id.label"); + } + $this->label = $label; return $this; @@ -497,6 +532,10 @@ class OptionFormGroup extends OptionFormItem public function addon($value) { + if ($value == OptionForm::AUTO_DETECT) { + $value = trans("options.$this->id.addon"); + } + $this->items[] = ['type' => 'addon', 'id' => null, 'value' => $value]; return $this; diff --git a/config/options.php b/config/options.php index 01021b46..ce334a3d 100644 --- a/config/options.php +++ b/config/options.php @@ -3,17 +3,17 @@ * @Author: printempw * @Date: 2016-07-29 11:53:11 * @Last Modified by: printempw - * @Last Modified time: 2016-12-31 13:25:58 + * @Last Modified time: 2016-12-31 23:14:51 */ return [ 'site_url' => '', 'site_name' => 'Blessing Skin Server', - 'site_description' => '开源的 PHP Minecraft 皮肤站', + 'site_description' => 'Open-source PHP Minecraft Skin Hosting Service', 'user_can_register' => '1', 'regs_per_ip' => '3', 'api_type' => '0', - 'announcement' => '欢迎使用 Blessing Skin Server {version}!', + 'announcement' => 'Welcome to Blessing Skin Server {version}!', 'color_scheme' => 'skin-blue', 'home_pic_url' => './resources/assets/images/bg.jpg', 'custom_css' => '', diff --git a/resources/lang/en/admin.yml b/resources/lang/en/admin.yml index 664e1156..7161b8d3 100644 --- a/resources/lang/en/admin.yml +++ b/resources/lang/en/admin.yml @@ -69,7 +69,9 @@ players: success: The player has been deleted successfully. customize: - change-color: Change theme color + change-color: + title: Change theme color + success: Theme color updated. colors: blue: Blue (Default) diff --git a/resources/lang/en/options.yml b/resources/lang/en/options.yml new file mode 100644 index 00000000..8314df08 --- /dev/null +++ b/resources/lang/en/options.yml @@ -0,0 +1,108 @@ +option-saved: Option Saved. + +homepage: + title: Homepage +home_pic_url: + title: Picture URL at Homepage + hint: Path relative to homepage or full URL. +favicon_url: + title: Website Icon + hint: Path relative to resources/assets/ or full URL. + description: The given image must have same width and height. +copyright_prefer: + title: Program Copyright + description: Any evil modification applied on the footer program copyright (including deleting, modifying author, changing link target) with out permission is FORBIDDEN. The author reserves the right to pursue relevant responsibilities. +copyright_text: + title: Custom Copyright Text + description: Placeholders are available in custom copyright text. e.g. {site_name} & {site_url} + +customJsCss: + title: Custom CSS/JavaScript + message: | + The contents will be attached to <style> and <script> tags.
+ - Here are some useful examples: Examples of Custom CSS JavaScript @GitHub WiKi +custom_css: CSS +custom_js: JavaScript + +rate: + title: About Scores +score_per_storage: + title: Storage + addon: scores = 1 KB +private_score_per_storage: + title: Private Storage + addon: scores = 1 KB + hint: Uploading private textures will cost more scores. +score_per_closet_item: + title: Favorites + addon: score = 1 closet item +return_score: + title: Score Return + label: Return scores back to user after deleting players/textures/closet items. +score_per_player: + title: Players + addon: scores = 1 player +user_initial_score: User Initial Score + +sign_in: + title: Signing In +sign_score: + title: Score Granted + addon1: scores ~ + addon2: scores +sign_gap_time: + title: Gap Time + addon: hours +sign_after_zero: + title: Time + label: Can sign in after 0 everyday + hint: The above option will be ignored if this is checked. + +general: + title: General Options +site_name: Site Name +site_description: Site Description +site_url: + title: Site URL + hint: Begin with http(s)://, nerver ends with slash +user_can_register: + title: Open Registration + label: Everyone is allowed to register +regs_per_ip: Max accounts of one IP +max_upload_file_size: + title: Max Upload Size + hint: "Limit of PHP in php.ini: :size" +allow_chinese_playername: + title: Player Name + label: Allow chinese player names +api_type: Prefered JSON API +auto_del_invalid_texture: + title: Invalid Textures + label: Delete invalid textures from skinlib automatically. + hint: Delete textures records whose file no longer exists automatically. +comment_script: + title: Comment Script + description: Placeholders are available in comment scripts. {tid} will be replaced with texture id, {name} will be replaced with texture name, {url} will be replaced with current URL. + +announ: + title: Site Announcement +announcement: + description: Styling with Markdown is supported. + +cache: + title: Resource Files + hint: Please adjust these options when CDN cache is on +force_ssl: + title: Force SSL + label: Force to use HTTPS protocol to load resources + hint: Check SSL available before turning on +auto_detect_asset_url: + title: Assets URL + label: Determine assets url automatically + description: Load asset files according to current URL. The site url will be used if this is not enabled. Please unable this if requests don't go through CDN. +return_200_when_notfound: + title: HTTP Response Code + label: Return 200 instead of 404 when requesting un-existent player +cache_expire_time: + title: Cache Exipre Time + hint: In seconds, 86400 = one day, 31536000 = one year diff --git a/resources/lang/zh_CN/admin.yml b/resources/lang/zh_CN/admin.yml index c82f47a4..de1c9d17 100644 --- a/resources/lang/zh_CN/admin.yml +++ b/resources/lang/zh_CN/admin.yml @@ -69,7 +69,9 @@ players: success: 角色已被成功删除 customize: - change-color: 更改配色 + change-color: + title: 更改配色 + success: 修改配色成功 colors: blue: 蓝色主题(默认) diff --git a/resources/lang/zh_CN/options.yml b/resources/lang/zh_CN/options.yml new file mode 100644 index 00000000..a570328e --- /dev/null +++ b/resources/lang/zh_CN/options.yml @@ -0,0 +1,108 @@ +option-saved: 设置已保存。 + +homepage: + title: 首页配置 +home_pic_url: + title: 首页图片地址 + hint: 相对于首页的路径或者完整的 URL +favicon_url: + title: 网站图标 + hint: 相对 resources/assets/ 的路径或者完整的 URL + description: 所使用的图像必须具有相同的宽度和高度 +copyright_prefer: + title: 程序版权信息 + description: 对于任何恶意修改页面右下角的版权信息(包括不限于删除、修改作者信息、修改链接指向)的用户,作者保留对其追究责任的权力。 +copyright_text: + title: 自定义版权文字 + description: 自定义版权文字内可使用占位符,{site_name} 将会被自动替换为站点名称,{site_url} 会被替换为站点地址。 + +customJsCss: + title: 自定义 CSS/JavaScript + message: | + 内容将会被追加至每个页面的 <style> 和 <script> 标签中。
+ - 这里有一些有用的示例:「自定义 CSS JavaScript」功能的一些实例@GitHub WiKi +custom_css: CSS +custom_js: JavaScript + +rate: + title: 积分换算 +score_per_storage: + title: 存储 + addon: 积分 = 1 KB +private_score_per_storage: + title: 私密材质存储 + addon: 积分 = 1 KB + hint: 上传私密材质将消耗更多积分 +score_per_closet_item: + title: 收藏消耗积分 + addon: 积分 = 一个衣柜物品 +return_score: + title: 积分返还 + label: 用户删除角色/材质/收藏时返还积分 +score_per_player: + title: 角色 + addon: 积分 = 一个角色 +user_initial_score: 新用户默认积分 + +sign_in: + title: 签到配置 +sign_score: + title: 签到获得积分 + addon1: 积分 ~ + addon2: 积分 +sign_gap_time: + title: 签到间隔时间 + addon: 小时 +sign_after_zero: + title: 签到时间 + label: 每天零点后可签到 + hint: 勾选后将无视上一条,每天零时后均可签到 + +general: + title: 常规选项 +site_name: 站点标题 +site_description: 站点描述 +site_url: + title: 站点地址(URL) + hint: 以 http(s):// 开头,不要以 / 结尾 +user_can_register: + title: 开放注册 + label: 任何人都可以注册 +regs_per_ip: 每个 IP 限制注册数 +max_upload_file_size: + title: 最大允许上传大小 + hint: PHP 限制::size,定义在 php.ini 中。 +allow_chinese_playername: + title: 角色名 + label: 允许中文角色名 +api_type: 首选 JSON API +auto_del_invalid_texture: + title: 失效材质 + label: 自动删除失效材质 + hint: 自动从皮肤库中删除文件不存在的材质记录 +comment_script: + title: 评论代码 + description: 评论代码内可使用占位符,{tid} 将会被自动替换为材质的 id,{name} 会被替换为材质名称,{url} 会被替换为当前页面地址。 + +announ: + title: 站点公告 +announcement: + description: 可使用 Markdown 进行排版 + +cache: + title: 资源文件配置 + hint: 如果启用了 CDN 缓存请适当修改这些配置 +force_ssl: + title: 强制 SSL + label: 强制使用 HTTPS 协议加载资源 + hint: 请确认 SSL 可用后再开启 +auto_detect_asset_url: + title: 资源地址 + label: 自动判断资源文件地址 + description: 根据当前 URL 自动加载资源文件,如果关闭则将根据「站点地址」填写的内容加载。如果出现 CDN 回源问题请关闭 +return_200_when_notfound: + title: HTTP 响应码 + label: 请求不存在的角色时返回 200 而不是 404 +cache_expire_time: + title: 缓存失效时间 + hint: 秒数,86400 = 一天,31536000 = 一年 diff --git a/resources/views/admin/customize.tpl b/resources/views/admin/customize.tpl index 259e383c..e8ffa316 100644 --- a/resources/views/admin/customize.tpl +++ b/resources/views/admin/customize.tpl @@ -25,7 +25,7 @@
-

{{ trans('admin.customize.change-color') }}

+

{{ trans('admin.customize.change-color.title') }}

diff --git a/resources/views/admin/options.tpl b/resources/views/admin/options.tpl index 675da70b..07b78b22 100644 --- a/resources/views/admin/options.tpl +++ b/resources/views/admin/options.tpl @@ -23,7 +23,7 @@
- {!! $forms['announcement']->render() !!} + {!! $forms['announ']->render() !!} {!! $forms['cache']->render() !!}