Load front-end i18n text at back-end

This commit is contained in:
Pig Fang 2019-09-07 17:18:58 +08:00
parent 7c0bf46c3c
commit 9ff8ea0893
13 changed files with 138 additions and 83 deletions

View File

@ -52,7 +52,6 @@ class AppServiceProvider extends ServiceProvider
'site_name' => option_localized('site_name'),
'route' => request()->path(),
'extra' => [],
'i18n' => ['_' => null],
];
$event->addContent('<script>var blessing = '.json_encode($blessing).';</script>');
});

View File

@ -0,0 +1,45 @@
<?php
namespace App\Services\Translations;
use Illuminate\Cache\Repository;
use Illuminate\Filesystem\Filesystem;
class JavaScript
{
/** @var Filesystem */
protected $filesystem;
/** @var Repository */
protected $cache;
/** @var Yaml */
protected $yaml;
protected $prefix = 'front-end-trans-';
public function __construct(Filesystem $filesystem, Repository $cache, Yaml $yaml)
{
$this->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");
}
}

View File

@ -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%",

2
public/lang/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -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 () {

View File

@ -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

View File

@ -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

View File

@ -1,9 +1,5 @@
@if (file_exists(resource_path($path = 'lang/overrides/'.config('app.locale').'/locale.js')))
<script src="{{ url('resources/'.$path) }}"></script>
@endif
@if (file_exists(resource_path($path = 'lang/overrides/'.config('app.fallback_locale').'/locale.js')))
<script src="{{ url('resources/'.$path) }}"></script>
@endif
@inject('intl', 'App\Services\Translations\JavaScript')
<script src="{{ $intl->generate(app()->getLocale()) }}"></script>
<script src="{{ webpack_assets('index.js') }}"></script>
<script>{!! option('custom_js') !!}</script>
{{-- Content added by plugins dynamically --}}

View File

@ -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');
}

View File

@ -0,0 +1,70 @@
<?php
namespace Tests;
use Illuminate\Cache\Repository;
use App\Services\Translations\Yaml;
use Illuminate\Filesystem\Filesystem;
use App\Services\Translations\JavaScript;
class JavaScriptTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
$this->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'));
}
}

View File

@ -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);
}
}

View File

@ -90,10 +90,6 @@ const config = {
'stylus-loader',
],
},
{
test: /\.ya?ml$/,
use: ['json-loader', 'yaml-loader'],
},
{
test: /\.(png|jpg|gif)$/,
loader: 'url-loader',

View File

@ -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"