From 5718567beaf1970ceec4e97561dd64466ece9aaa Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Sat, 7 Sep 2019 23:20:16 +0800 Subject: [PATCH] Load front end i18n of plugin automatically --- app/Listeners/GeneratePluginTranslations.php | 46 +++++++++++++++++++ app/Providers/EventServiceProvider.php | 2 + app/Services/Translations/JavaScript.php | 10 ++++ app/Services/Translations/Loader.php | 2 +- app/Services/Translations/Yaml.php | 2 +- resources/misc/changelogs/en/5.0.0.md | 1 + resources/misc/changelogs/zh_CN/5.0.0.md | 1 + .../common/dependencies/script.blade.php | 1 + .../GeneratePluginTranslationsTest.php | 40 ++++++++++++++++ .../TranslationsTest/JavaScriptTest.php | 21 +++++++++ 10 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 app/Listeners/GeneratePluginTranslations.php create mode 100644 tests/ListenersTest/GeneratePluginTranslationsTest.php diff --git a/app/Listeners/GeneratePluginTranslations.php b/app/Listeners/GeneratePluginTranslations.php new file mode 100644 index 00000000..a0a714f9 --- /dev/null +++ b/app/Listeners/GeneratePluginTranslations.php @@ -0,0 +1,46 @@ +filesystem = $filesystem; + $this->plugins = $plugins; + } + + public function handle() + { + $plugins = $this->plugins->getEnabledPlugins(); + $locales = array_keys(config('locales')); + + array_walk($locales, function ($locale) use ($plugins) { + $i18n = $plugins + ->filter(function (Plugin $plugin) use ($locale) { + return $this->filesystem->exists( + $plugin->getPath()."/lang/$locale/front-end.yml" + ); + }) + ->map(function (Plugin $plugin) use ($locale) { + return trans($plugin->namespace.'::front-end'); + }); + + if ($i18n->isNotEmpty()) { + $content = 'Object.assign(blessing.i18n, '. + $i18n->toJson(JSON_UNESCAPED_UNICODE).')'; + $this->filesystem->put(public_path("lang/${locale}_plugin.js"), $content); + } + }); + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index ab4b4dca..145e1ab8 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -23,9 +23,11 @@ class EventServiceProvider extends ServiceProvider ], 'App\Events\PluginWasEnabled' => [ 'App\Listeners\CopyPluginAssets', + 'App\Listeners\GeneratePluginTranslations', ], 'App\Events\PluginVersionChanged' => [ 'App\Listeners\CopyPluginAssets', + 'App\Listeners\GeneratePluginTranslations', ], 'App\Events\PluginBootFailed' => [ 'App\Listeners\NotifyFailedPlugin', diff --git a/app/Services/Translations/JavaScript.php b/app/Services/Translations/JavaScript.php index ea8c9dc5..28be4f24 100644 --- a/app/Services/Translations/JavaScript.php +++ b/app/Services/Translations/JavaScript.php @@ -38,4 +38,14 @@ class JavaScript return url("lang/$locale.js?t=$compiledModified"); } + + public function plugin(string $locale): string + { + $path = public_path("lang/${locale}_plugin.js"); + if ($this->filesystem->exists($path)) { + return url("lang/${locale}_plugin.js?t=".$this->filesystem->lastModified($path)); + } + + return ''; + } } diff --git a/app/Services/Translations/Loader.php b/app/Services/Translations/Loader.php index 723bb118..0b6ddb45 100644 --- a/app/Services/Translations/Loader.php +++ b/app/Services/Translations/Loader.php @@ -13,7 +13,7 @@ class Loader extends TranslationLoaderManager $full = "{$path}/{$locale}/{$group}.yml"; return count($translations) === 0 && $this->files->exists($full) - ? resolve(Yaml::class)->loadYaml($full) + ? resolve(Yaml::class)->parse($full) : []; } } diff --git a/app/Services/Translations/Yaml.php b/app/Services/Translations/Yaml.php index 7648b410..bc6cc9d4 100644 --- a/app/Services/Translations/Yaml.php +++ b/app/Services/Translations/Yaml.php @@ -15,7 +15,7 @@ class Yaml $this->cache = $cache; } - public function loadYaml(string $path): array + public function parse(string $path): array { $key = 'yaml-trans-'.md5($path).'-'.filemtime($path); diff --git a/resources/misc/changelogs/en/5.0.0.md b/resources/misc/changelogs/en/5.0.0.md index a52fb783..49713043 100644 --- a/resources/misc/changelogs/en/5.0.0.md +++ b/resources/misc/changelogs/en/5.0.0.md @@ -15,6 +15,7 @@ - Refactor account system. - PHP version requirement is increased to 7.2.0. - Use `install.lock` file to detect status of installation. +- Load front end i18n text from `lang/front-end.yml` of a plugin automatically. ## Fixed diff --git a/resources/misc/changelogs/zh_CN/5.0.0.md b/resources/misc/changelogs/zh_CN/5.0.0.md index 773dbccf..5a46d77f 100644 --- a/resources/misc/changelogs/zh_CN/5.0.0.md +++ b/resources/misc/changelogs/zh_CN/5.0.0.md @@ -15,6 +15,7 @@ - 重构用户系统 - PHP 版本最低要求为 7.2.0 - 使用 `install.lock` 文件来检测安装状态 +- 插件系统:自动从 `lang/front-end.yml` 中加载前端多语言 ## 修复 diff --git a/resources/views/common/dependencies/script.blade.php b/resources/views/common/dependencies/script.blade.php index 55005e6a..3c62af84 100644 --- a/resources/views/common/dependencies/script.blade.php +++ b/resources/views/common/dependencies/script.blade.php @@ -1,5 +1,6 @@ @inject('intl', 'App\Services\Translations\JavaScript') + {{-- Content added by plugins dynamically --}} diff --git a/tests/ListenersTest/GeneratePluginTranslationsTest.php b/tests/ListenersTest/GeneratePluginTranslationsTest.php new file mode 100644 index 00000000..980a2b6e --- /dev/null +++ b/tests/ListenersTest/GeneratePluginTranslationsTest.php @@ -0,0 +1,40 @@ + ['en' => [], 'jp' => []]]); + $this->mock(PluginManager::class, function ($mock) { + $mock->shouldReceive('getEnabledPlugins') + ->with() + ->once() + ->andReturn(collect([new Plugin('/reina', ['namespace' => 'れいな'])])); + }); + $this->mock(Filesystem::class, function ($mock) { + $mock->shouldReceive('exists') + ->with('/reina/lang/en/front-end.yml') + ->once() + ->andReturn(false); + $mock->shouldReceive('exists') + ->with('/reina/lang/jp/front-end.yml') + ->once() + ->andReturn(true); + $mock->shouldReceive('put') + ->with( + public_path('lang/jp_plugin.js'), + 'Object.assign(blessing.i18n, ["れいな::front-end"])' + ) + ->once(); + }); + + $this->app->call('App\Listeners\GeneratePluginTranslations@handle'); + } +} diff --git a/tests/ServicesTest/TranslationsTest/JavaScriptTest.php b/tests/ServicesTest/TranslationsTest/JavaScriptTest.php index 5267169c..e9598640 100644 --- a/tests/ServicesTest/TranslationsTest/JavaScriptTest.php +++ b/tests/ServicesTest/TranslationsTest/JavaScriptTest.php @@ -65,4 +65,25 @@ class JavaScriptTest extends TestCase $this->assertEquals(url('lang/en.js?t=1'), resolve(JavaScript::class)->generate('en')); } + + public function testPlugin() + { + $this->mock(Filesystem::class, function ($mock) { + $mock->shouldReceive('exists') + ->with(public_path('lang/en_plugin.js')) + ->twice() + ->andReturn(false, true); + $mock->shouldReceive('lastModified') + ->with(public_path('lang/en_plugin.js')) + ->once() + ->andReturn(1); + }); + + $this->assertEquals('', resolve(JavaScript::class)->plugin('en')); + + $this->assertEquals( + url('lang/en_plugin.js?t=1'), + resolve(JavaScript::class)->plugin('en') + ); + } }