构建 Laravel 翻译包 - 连接前端
发布日期:作者: Joe Dixon
在该系列的 上一期中,我们讨论了将应用程序语言文件中的翻译转换成我们可以开始与之交互的格式的过程。在本文中,我们将连接前端,准备开始构建用户界面,以帮助用户进行翻译管理。
UI 将使用社区最喜欢的框架 Tailwind CSS 和 Vue.js 进行开发。
方法
无论你喜欢还是讨厌,我将直接从 Caleb Porzio 的 拥抱后端 的理念中汲取灵感,用于构建这个包。在演讲中,Caleb 提出了一个概念,即不再将 Javascript 用于构建单页应用程序,包括使其负责检索所有数据,以及路由和表单提交等操作。相反,他建议利用 Laravel 的优势来实现更混合的方法。受到这一理念的启发,我们将利用我们的控制器和 Blade 视图传递 Vue.js 组件所需的数据,以添加必要的动态功能。 Laravel Mix 将用于构建和编译包资源。
路由
首先,我们需要告诉 Laravel 从哪里加载我们的路由。一种方法是在包的 TranslationServiceProvider
中使用 loadRoutesFrom
方法。此方法继承自父类 Illuminate\Support\ServiceProvider
。
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
这使我们能够像在 Laravel 应用程序中一样,在一个文件中定义所有包路由。
Route::group(config('translation.route_group_config') + ['namespace' => 'JoeDixon\\Translation\\Http\\Controllers'], function ($router) { $router->get(config('translation.ui_url'), 'LanguageController@index') ->name('languages.index'); $router->get(config('translation.ui_url').'/{language}/translations', 'LanguageTranslationController@index') ->name('languages.translations.index'); ...});
在这个文件中,我们使用 Route::group()
方法来引入任何自定义分组配置,这些配置将与包控制器所在的命名空间合并。
需要注意的另一件事是,配置再次用于动态注册用户希望路由的位置。如果保留默认配置选项,ui_url
将设置为 languages
。因此,上面的路由将按以下方式注册
my-app.test/languagesmy-app.test/languages/{language}/translations
在这个文件中,定义了路由来列出、创建和存储语言,以及列出、创建、存储和更新翻译。
控制器
服务提供者不需要为控制器进行任何连接。只要它们位于路由文件中定义的命名空间中,一切都会按预期工作。
在每个控制器中,几乎每个方法都需要访问我们在该系列的 上一篇文章 中创建的翻译驱动程序。因此,我们将在构造函数中从容器中解析它。
public function __construct(Translation $translation){ $this->translation = $translation;}
现在,无论驱动程序如何,我们都可以轻松地使用我们已经构建的功能来从控制器内部与项目的翻译进行交互。
public function index(Request $request){ $languages = $this->translation->allLanguages(); return view('translation::languages.index', compact('languages'));}
这里唯一可能看起来有点奇怪的是加载视图的方式。translation::
只是告诉 Laravel 从翻译包命名空间加载视图,Laravel 在服务提供者中已经了解了这个命名空间。后面会详细说明。
视图
首先,我们需要告诉 Laravel 从哪里加载包的路由。
$this->loadViewsFrom(__DIR__.'/../resources/views', 'translation');
通过在包服务提供者的 boot
方法中使用 loadViewsFrom
方法,Laravel 知道我们的路由应该从 /package/root/resources/views
加载,并使用 translation
命名空间。使用命名空间可以降低包之间或甚至与主应用程序之间视图冲突的风险。
$this->publishes([ __DIR__.'/../resources/views' => resource_path('views/vendor/translation'),]);
上面的代码行告诉 Laravel 视图的位置,以及如果包使用者希望将它们拉入自己的应用程序中,应该将它们复制到哪里。
在这种情况下,它们将从 /package/root/resources/views
复制到应用程序的 资源路径 中的 views/vendor/translation
。
通常,这样做是为了让使用者能够根据自己的需求进行编辑。
资源
为了我自己方便,我喜欢使用 Laravel Mix 来构建我的包的资源。它提供了很棒的开发体验,而且设置起来快速简便。
我从项目的根目录运行 npm init
开始,然后按照说明设置环境。
现在,我们可以通过运行 npm install laravel-mix --save-dev
来安装 Laravel Mix。这将安装所有必需的依赖项,并将 Laravel Mix 作为开发依赖项添加到 package.json
文件中。
接下来,我们需要将 Mix 附带的 webpack.mix.js
文件复制到项目的根目录,以便我们可以开始配置构建。
cp node_modules/laravel-mix/setup/webpack.mix.js ./
CSS
接下来,我们将把 CSS 框架 Tailwind 安装并配置到我们的包中。为此,通过运行 npm install tailwindcss --save-dev
来引入依赖项。
有了依赖项后,我们就可以开始配置安装。首先,我们将生成 Tailwind 配置文件。这可以通过运行 ./node_modules/.bin/tailwind init tailwind.js
来实现,其中 tailwind.js
是要生成的配置文件的名称。这个文件允许您调整基本颜色设置、字体和字体大小、宽度和高度,以及更多其他设置。值得一看或阅读 Tailwind 的 文档 以了解更多信息。但是,在本教程中,我们将继续使用优秀的默认值。
最后,我们需要告诉 Laravel Mix 在构建过程中使用 Tailwind 配置运行 PostCSS。
为此,我们首先需要在 webpack.mix.js
文件中引入 Tailwind PostCSS 插件。
var tailwindcss = require('tailwindcss');
然后,作为构建流程的一部分,我们可以使用 Mix 的 postCss
方法,传入上面 tailwindcss
变量中存储的导出函数来配置构建的这一步。
mix.postCss('resources/assets/css/main.css', 'css', [ tailwindcss('./tailwind.js'),]);
这个方法表示,读取 resources/assets/css/main.css
中的文件,应用 tailwind PostCSS 插件,并将输出到 css
目录。
现在,当我们运行 npm run dev|production|watch
时,这个过程会自动执行。
Javascript
我们将使用 Vue.js 开发 UI,因此需要将其作为依赖项引入。我们还需要一些 ajax 功能,所以让我们也安装流行的 axios 包来完成繁重的工作。
npm install vue axios
发布
在上面,我们要求 Mix 将资源构建到 css
和 js
目录中,但我们需要告诉它在相对于 webpack.mix.js
文件的位置找到它们。这可以使用以下方法来完成。
mix.setPublicPath('public/assets');
在标准的 Laravel 应用程序中,这将用于将构建的资源发布到公开可访问的位置。但是,在我们的包范围内,我们需要将它们发布到一个位置,以便可以使用 php artisan publish
命令轻松地发布它们。这允许最终用户将文件发布到他们的应用程序中,他们可以在其中自由地修改它们并将它们保存在自己的版本控制中。
最后,我们需要告诉 Laravel 从哪里找到要发布的文件。这同样是在服务提供者中完成的。
$this->publishes([ __DIR__.'/../public/assets' => public_path('vendor/translation'),], 'assets');
第一个参数是一个数组,其中键表示包中资产的路径,而值表示它们在应用程序中应该发布的位置。第二个参数是定义正在发布的文件类型的标签。这为用户提供了灵活性,可以选择他们希望发布的文件类型作为发布命令的选项。
提示
在开发过程中,您可能不希望每次想要测试更改时都必须运行发布 artisan 命令。为了减轻这种负担,将 `mix.setPublicPath` 方法更新为要在测试中加载资产的路径。但是,在准备提交时不要忘记更改它!使用环境变量来管理这种状态是一个很好的方法。
现在我们已经奠定了基础,可以开始构建实现用户界面的路由、控制器、视图和资产,我们将在下一部分中介绍。