如何在 JS(vue)文件中使用 Laravel 翻译?
由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!
经过一番研究,我发现现有的解决方案都无法满足我的需求。大多数方案都需要重新编译 JS 资源,或者在编辑或添加新翻译后运行一些 Artisan 命令,我不喜欢这种方式。或许已经有一些解决方案了,但我记得我曾在 Laravel Nova 中看到过我需要的东西。
所以我查看了 Laravel Nova 的源代码,发现 Laravel 的翻译是以 JSON 格式从翻译文件中加载的,然后传递给 Blade 模板。在 Blade 模板中,这只是简单地赋值给一个全局配置变量。
该方案的问题在于它只加载JSON翻译,而 Laravel 也支持PHP短语。
经过一番谷歌搜索,我找到了一篇文章,作者在文章中展示了如何将 PHP 语言短语加载到 JS 中。
我结合了 Laravel Nova 源代码和上面文章中的两种方法,最终找到了我认为在 JS 文件中使用 Laravel 翻译字符串的最简单方法。
首先,创建一个翻译服务提供商:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;
class TranslationServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
Cache::rememberForever('translations', function () {
$translations = collect();
foreach (['en', 'kg', 'ru'] as $locale) { // suported locales
$translations[$locale] = [
'php' => $this->phpTranslations($locale),
'json' => $this->jsonTranslations($locale),
];
}
return $translations;
});
}
private function phpTranslations($locale)
{
$path = resource_path("lang/$locale");
return collect(File::allFiles($path))->flatMap(function ($file) use ($locale) {
$key = ($translation = $file->getBasename('.php'));
return [$key => trans($translation, [], $locale)];
});
}
private function jsonTranslations($locale)
{
$path = resource_path("lang/$locale.json");
if (is_string($path) && is_readable($path)) {
return json_decode(file_get_contents($path), true);
}
return [];
}
}
config/app.php在文件中注册:
'providers' => [
// your other providers
App\Providers\TranslationServiceProvider::class,
],
然后,你需要在 Blade 模板中将翻译字符串传递给 JS。我是在默认layouts/app.blade.php文件中完成的:
<script>
window._locale = '{{ app()->getLocale() }}';
window._translations = {!! cache('translations') !!};
</script>
现在你需要一些 JavaScript 函数来获取翻译并应用替换。为此,我创建了一个trans.js文件:
module.exports = {
methods: {
/**
* Translate the given key.
*/
__(key, replace) {
let translation, translationNotFound = true
try {
translation = key.split('.').reduce((t, i) => t[i] || null, window._translations[window._locale].php)
if (translation) {
translationNotFound = false
}
} catch (e) {
translation = key
}
if (translationNotFound) {
translation = window._translations[window._locale]['json'][key]
? window._translations[window._locale]['json'][key]
: key
}
_.forEach(replace, (value, key) => {
translation = translation.replace(':' + key, value)
})
return translation
}
},
}
这是 Laravel Nova 的一个修改版本,base.js它也加载 PHP 翻译。简而言之,其逻辑是:首先尝试在 PHP 翻译中查找翻译字符串,如果找不到,则尝试在 JSON 翻译中查找。如果仍然找不到翻译,则会显示键本身。
最后一步是将该方法作为 mixin 引入:
Vue.mixin(require('./trans'))
就这样。现在你可以在 Vue 组件中使用翻译了,就像这样:
<template>
<div class="card">
<div class="card-header">{{ __('Example Component') }}</div>
<div class="card-body">
{{ __("I'm an example component.") }}
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log(this.__('Component mounted.'))
}
}
</script>
使用此方案,您在编辑/添加新翻译后只需运行cache:clearartisan 命令即可。Laravel Nova(我们在项目中使用的框架)自带软件包,可以直接从管理面板执行此类命令,因此完全不存在兼容性问题。
更新于2020年2月25日
之前的解决方案仅在单一语言环境下有效。感谢@morpheus_ro指出这一点。现在,该解决方案已涵盖应用程序中指定的所有语言环境。
文章来源:https://dev.to/4unkur/how-to-use-laravel-translations-in-js-vue-files-ia