From 9ff8ea0893354fbd53895d256c58cc8308664548 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Sat, 7 Sep 2019 17:18:58 +0800 Subject: [PATCH] Load front-end i18n text at back-end --- app/Providers/AppServiceProvider.php | 1 - app/Services/Translations/JavaScript.php | 45 ++++++++++++ package.json | 4 +- public/lang/.gitignore | 2 + resources/assets/src/scripts/i18n-text.ts | 32 ++------- resources/lang/en/front-end.yml | 16 ----- resources/lang/zh_CN/front-end.yml | 16 ----- .../common/dependencies/script.blade.php | 8 +-- tests/AdminConfigurationsTest.php | 5 ++ .../TranslationsTest/JavaScriptTest.php | 70 +++++++++++++++++++ tests/TestCase.php | 6 ++ webpack.config.js | 4 -- yarn.lock | 12 +--- 13 files changed, 138 insertions(+), 83 deletions(-) create mode 100644 app/Services/Translations/JavaScript.php create mode 100644 public/lang/.gitignore create mode 100644 tests/ServicesTest/TranslationsTest/JavaScriptTest.php diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 1d59b901..d4318ecd 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -52,7 +52,6 @@ class AppServiceProvider extends ServiceProvider 'site_name' => option_localized('site_name'), 'route' => request()->path(), 'extra' => [], - 'i18n' => ['_' => null], ]; $event->addContent(''); }); diff --git a/app/Services/Translations/JavaScript.php b/app/Services/Translations/JavaScript.php new file mode 100644 index 00000000..ef52204f --- /dev/null +++ b/app/Services/Translations/JavaScript.php @@ -0,0 +1,45 @@ +filesystem = $filesystem; + $this->cache = $cache; + $this->yaml = $yaml; + } + + public function generate(string $locale): string + { + $source = resource_path("lang/$locale/front-end.yml"); + $compiled = public_path("lang/$locale.js"); + $sourceModified = $this->filesystem->lastModified($source); + $compiledModified = intval($this->cache->get($this->prefix.$locale, 0)); + + if ($sourceModified > $compiledModified || ! $this->filesystem->exists($compiled)) { + $content = 'blessing.i18n='.json_encode($this->yaml->loadYaml($source), JSON_UNESCAPED_UNICODE); + $this->filesystem->put($compiled, $content); + $this->cache->put($this->prefix.$locale, $sourceModified); + + return url("lang/$locale.js?t=$sourceModified"); + } + + return url("lang/$locale.js?t=$compiledModified"); + } +} diff --git a/package.json b/package.json index 6c60665a..d2365fbf 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "fs-extra": "^7.0.1", "jest": "^24.7.1", "jest-extended": "^0.11.1", - "json-loader": "^0.5.7", "mini-css-extract-plugin": "^0.6.0", "node-sass": "^4.12.0", "postcss-loader": "^3.0.0", @@ -92,8 +91,7 @@ "webpack-cli": "^3.3.1", "webpack-dev-server": "^3.3.1", "webpack-manifest-plugin": "^2.0.4", - "webpackbar": "^3.1.5", - "yaml-loader": "^0.5.0" + "webpackbar": "^3.1.5" }, "browserslist": [ "> 1%", diff --git a/public/lang/.gitignore b/public/lang/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/public/lang/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/resources/assets/src/scripts/i18n-text.ts b/resources/assets/src/scripts/i18n-text.ts index 2ad505a3..fae88eef 100644 --- a/resources/assets/src/scripts/i18n-text.ts +++ b/resources/assets/src/scripts/i18n-text.ts @@ -1,35 +1,15 @@ -import { locale as elementLocale } from 'element-ui' +// @ts-ignore +import { locale } from 'element-ui' import { emit } from './event' -declare module 'element-ui/types/element-ui' { - export const locale: { - use(i18n: any): void - } -} - const langs = { - en: { - bs: () => import('../../../lang/en/front-end.yml'), - element: () => import('element-ui/lib/locale/lang/en'), - }, - zh_CN: { - bs: () => import('../../../lang/zh_CN/front-end.yml'), - element: () => import('element-ui/lib/locale/lang/zh-CN'), - }, + en: () => import('element-ui/lib/locale/lang/en'), + zh_CN: () => import('element-ui/lib/locale/lang/zh-CN'), } async function load(language: import('../shims').I18n) { - const { bs: loadBS, element: loadElement } = langs[language] - await Promise.all([ - (async () => { - const text = await loadBS() - blessing.i18n = Object.assign(blessing.i18n || Object.create(null), text) - emit('i18nLoaded', blessing.i18n) - })(), - (async () => { - elementLocale.use((await loadElement()).default) - })(), - ]) + locale.use((await langs[language]()).default) + emit('i18nLoaded', blessing.i18n) } export default function () { diff --git a/resources/lang/en/front-end.yml b/resources/lang/en/front-end.yml index 8ba7a4c5..90fe92f6 100644 --- a/resources/lang/en/front-end.yml +++ b/resources/lang/en/front-end.yml @@ -296,22 +296,6 @@ admin: updateButton: Update Now downloading: Downloading... updateCompleted: Update completed. - change-color: - title: Change theme color - success: Theme color updated. - colors: - blue: Blue (Default) - blue-light: Blue Light - yellow: Yellow - yellow-light: Yellow Light - green: Green - green-light: Green Light - purple: Purple - purple-light: Purple Light - red: Red - red-light: Red Light - black: Black - black-light: Black Light report: tid: Texture ID diff --git a/resources/lang/zh_CN/front-end.yml b/resources/lang/zh_CN/front-end.yml index b120cf27..03c5f8d2 100644 --- a/resources/lang/zh_CN/front-end.yml +++ b/resources/lang/zh_CN/front-end.yml @@ -288,22 +288,6 @@ admin: updateButton: 马上升级 downloading: 正在下载更新包 updateCompleted: 更新完成 - change-color: - title: 更改配色 - success: 修改配色成功 - colors: - blue: 蓝色主题(默认) - blue-light: 蓝色主题 - 白色侧边栏 - yellow: 黄色主题 - yellow-light: 黄色主题 - 白色侧边栏 - green: 绿色主题 - green-light: 绿色主题 - 白色侧边栏 - purple: 基佬紫 - purple-light: 紫色主题 - 白色侧边栏 - red: 喜庆红(笑) - red-light: 红色主题 - 白色侧边栏 - black: 高端黑 - black-light: 黑色主题 - 白色侧边栏 report: tid: 材质 ID diff --git a/resources/views/common/dependencies/script.blade.php b/resources/views/common/dependencies/script.blade.php index 00d06c05..55005e6a 100644 --- a/resources/views/common/dependencies/script.blade.php +++ b/resources/views/common/dependencies/script.blade.php @@ -1,9 +1,5 @@ -@if (file_exists(resource_path($path = 'lang/overrides/'.config('app.locale').'/locale.js'))) - -@endif -@if (file_exists(resource_path($path = 'lang/overrides/'.config('app.fallback_locale').'/locale.js'))) - -@endif +@inject('intl', 'App\Services\Translations\JavaScript') + {{-- Content added by plugins dynamically --}} diff --git a/tests/AdminConfigurationsTest.php b/tests/AdminConfigurationsTest.php index 3715444b..a45edff9 100644 --- a/tests/AdminConfigurationsTest.php +++ b/tests/AdminConfigurationsTest.php @@ -4,6 +4,7 @@ namespace Tests; use Cache; use Redis; +use Mockery; use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\DatabaseTransactions; @@ -15,6 +16,10 @@ class AdminConfigurationsTest extends BrowserKitTestCase { // Do not use `WithoutMiddleware` trait parent::setUp(); + $this->instance( + \App\Services\Translations\JavaScript::class, + Mockery::spy(\App\Services\Translations\JavaScript::class) + ); $this->actAs('admin'); } diff --git a/tests/ServicesTest/TranslationsTest/JavaScriptTest.php b/tests/ServicesTest/TranslationsTest/JavaScriptTest.php new file mode 100644 index 00000000..ebcd1f4e --- /dev/null +++ b/tests/ServicesTest/TranslationsTest/JavaScriptTest.php @@ -0,0 +1,70 @@ +app->forgetInstance(JavaScript::class); + } + + public function testGenerateFreshFile() + { + $this->mock(Filesystem::class, function ($mock) { + $mock->shouldReceive('lastModified') + ->with(resource_path('lang/en/front-end.yml')) + ->once() + ->andReturn(1); + $mock->shouldReceive('put') + ->with(public_path('lang/en.js'), 'blessing.i18n={"a":"b"}') + ->once() + ->andReturn(1); + }); + $this->mock(Repository::class, function ($mock) { + $mock->shouldReceive('get') + ->with('front-end-trans-en', 0) + ->once() + ->andReturn(0); + $mock->shouldReceive('put') + ->with('front-end-trans-en', 1) + ->once(); + }); + $this->mock(Yaml::class, function ($mock) { + $mock->shouldReceive('loadYaml') + ->with(resource_path('lang/en/front-end.yml')) + ->once() + ->andReturn(['a' => 'b']); + }); + + $this->assertEquals(url('lang/en.js?t=1'), resolve(JavaScript::class)->generate('en')); + } + + public function testGenerateCached() + { + $this->mock(Filesystem::class, function ($mock) { + $mock->shouldReceive('lastModified') + ->with(resource_path('lang/en/front-end.yml')) + ->once() + ->andReturn(1); + $mock->shouldReceive('exists') + ->with(public_path('lang/en.js')) + ->once() + ->andReturn(true); + }); + $this->mock(Repository::class, function ($mock) { + $mock->shouldReceive('get') + ->with('front-end-trans-en', 0) + ->once() + ->andReturn(1); + }); + + $this->assertEquals(url('lang/en.js?t=1'), resolve(JavaScript::class)->generate('en')); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index de43ef4b..dc969d01 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -50,4 +50,10 @@ class TestCase extends \Illuminate\Foundation\Testing\TestCase return $this->actingAs($role); } + + protected function setUp(): void + { + parent::setUp(); + $this->spy(\App\Services\Translations\JavaScript::class); + } } diff --git a/webpack.config.js b/webpack.config.js index f513b0fb..90cbd2ad 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -90,10 +90,6 @@ const config = { 'stylus-loader', ], }, - { - test: /\.ya?ml$/, - use: ['json-loader', 'yaml-loader'], - }, { test: /\.(png|jpg|gif)$/, loader: 'url-loader', diff --git a/yarn.lock b/yarn.lock index badf3bd7..fb864fd8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5656,7 +5656,7 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.5.2, js-yaml@^3.9.0: +js-yaml@^3.9.0: version "3.12.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" dependencies: @@ -5717,10 +5717,6 @@ jsesc@~0.5.0: resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= -json-loader@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" - json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -9965,12 +9961,6 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== -yaml-loader@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/yaml-loader/-/yaml-loader-0.5.0.tgz#86b1982d84a8e429e6647d93de9a0169e1c15827" - dependencies: - js-yaml "^3.5.2" - yargs-parser@10.x: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"