Building a Laravel Translation Package – Wiring Up The Frontend

Published on by

Building a Laravel Translation Package – Wiring Up The Frontend image

In the last installment of this series, we talked through the process of manipulating the translations in our application’s language files into a format where we are now in a position to start interacting with them. In this article, we’ll be wiring up the frontend ready to start building out the user interface which will aid users with the process of translation management.

The UI will be developed using the community favorites, Tailwind CSS and Vue.js.

The Approach

Like it or loathe it, I’m taking a leaf straight out of the Caleb Porzio book of embracing the backend for this package. In his talk, Caleb presents the notion of taking the emphasis away from using Javascript to build single page applications including making it responsible for retrieving all of its data as well as things like routing and form submissions. Instead, he suggests using strengths of Laravel to produce a more hybrid approach. Taking inspiration from this, we’ll be leveraging our controllers and blade views to pass the data required by our Vue.js components to add the necessary dynamic functionality. Laravel Mix will be utilized to build and compile the package assets.

Routes

To start, we’ll need to tell Laravel where to load our routes from. One way to do this is by using the loadRoutesFrom method inside of our package’s TranslationServiceProvider. This method is inherited from the parent Illuminate\Support\ServiceProvider class.

$this->loadRoutesFrom(__DIR__.'/../routes/web.php');

This allows us to define all the package routes in one file in the same way you would in your Laravel application.

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

In this file, we use the Route::group() method to pull in any custom group configuration which is merged with the namespace from where the package controllers reside.

The only other thing to note is that the configuration is again used to dynamically register the routes where the user wants them. If left to the default configuration options, the ui_url is set to languages. As such, the above routes will be registered as follows:

my-app.test/languages
my-app.test/languages/{language}/translations

In this file, routes are defined to list, create and store languages and list, create, store and update translations.

Controllers

There is no wiring in the service provider required for controllers. As long as they are found at the namespace defined in the routes file, everything will work as expected.

In each of the controllers, access to the translation drivers we created in the previous article in this series, is required from just about every method. As such, we’ll resolve it from the container in the constructor.

public function __construct(Translation $translation)
{
$this->translation = $translation;
}

Now, regardless of the driver, it’s trivial to use the functionality we have already built to interact with the project’s translations from within the controller.

public function index(Request $request)
{
$languages = $this->translation->allLanguages();
 
return view('translation::languages.index', compact('languages'));
}

The only thing which may look a little alien here is the way the view is loaded. translation:: simply tells Laravel to load the view from the translation package namespace which Laravel is made aware of in the service provider. More on that to follow.

Views

First, we need to tell Laravel where the routes for the package should be loaded from.

$this->loadViewsFrom(__DIR__.'/../resources/views', 'translation');

By using the loadViewsFrom method in the boot method of the package service provider, Laravel knows that our routes should be loaded from /package/root/resources/views using the translation namespace. Using a namespace mitigates the risk of views conflicting between packages or even the main application.

$this->publishes([
__DIR__.'/../resources/views' => resource_path('views/vendor/translation'),
]);

The above line tells Laravel where the views can be found and where they should be copied to should the package consumer wish to pull them into their application.

In this case, they would be copied from /package/root/resources/views to views/vendor/translation within the resource path of the application.

Typically, this is done so the consumer is able to edit them to suit their own requirements.

Assets

For my own sanity, I like to use Laravel Mix to build assets for my packages. It offers a great developer experience and is quick and easy to get up and running.

I start by running npm init from the root of the project and following the instructions to setup the environment.

Now it’s possible to install Laravel Mix by running npm install laravel-mix --save-dev. This will install all the required dependencies as well as add Laravel Mix as a development dependency to the package.json file.

Next, we need to copy the webpack.mix.js file which ships with Mix to the root of the project so we can start configuring the build.

cp node_modules/laravel-mix/setup/webpack.mix.js ./

CSS

Next, we will install and configure the CSS framework, Tailwind, into our package. To do this, pull in the dependency by running npm install tailwindcss --save-dev.

With the dependencies available, we can now start to configure the installation. First, we’ll generate the Tailwind configuration file. This can be achieved by running ./node_modules/.bin/tailwind init tailwind.js where tailwind.js is the name the configuration file will be generated as. This file allows you to tweak the base color settings, fonts and font sizes, widths and heights and much, much more. It’s worth taking a look at this or reading the Tailwind documentation for further information. However, for the purposes of this tutorial, we will continue with the excellent default values.

Finally, we need to tell Laravel Mix to run PostCSS using the Tailwind configuration as part of the build.

To do this, we first need to require the Tailwind PostCSS plugin in the webpack.mix.js file.

var tailwindcss = require('tailwindcss');

Then as part of the build pipeline, we can use Mix’s postCss method, passing in the exported function stored in the tailwindcss variable above to configure this step of the build.

mix.postCss('resources/assets/css/main.css', 'css', [
tailwindcss('./tailwind.js'),
]);

This method is saying, take the file at resources/assets/css/main.css, apply the tailwind PostCSS plugin and output to the css directory.

Now when we run npm run dev|production|watch, this process will run automagically.

Javascript

We will develop the UI using Vue.js, so this will need to be pulled in as a dependency. We will also require a little bit of ajax functionality so let’s also install the popular axios package to do the heavy lifting for us.

npm install vue axios

Publishing

Above, we have asked Mix to build the assets into the css and js directories, but we need to tell it where to find them in relation to the webpack.mix.js file. The can be done using the following method.

mix.setPublicPath('public/assets');

In a standard Laravel application, this would be used to publish the built assets to a publicly available location. However, in our package scope, we need to publish them to a location where they can easily be published using the php artisan publish command. This allows an end user to publish the files to their application where they are free to modify them and keep them within their own version control.

Finally, we need to tell Laravel where to find the files for publishing. This is, again, carried out in the Service Provider.

$this->publishes([
__DIR__.'/../public/assets' => public_path('vendor/translation'),
], 'assets');

The first argument is an array where the key represents the path to the assets within the package, and the value represents the location where they should be published within the app. The second argument is a tag defining the type of files being published. This provides the user the flexibility to choose the types of file they wish to publish as an option to the publish command.

Tip

In development, you will likely not want to have to run the publish artisan command every time you want to test your changes. To mitigate this, update the mix.setPublicPath method to the path you wish to load the assets from in testing. However, don’t forget to change it back when you are ready to commit! An excellent way to manage this state is by using environment variables.

We now have the groundwork in place to start fleshing out the routes, controllers, views, and assets needed to bring the user interface to life, which we’ll cover in the next installment.

Joe Dixon photo

Founder and CTO of ubisend. Proud Father to two tiny heroes, Husband, developer, occasional globetrotter.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
Paragraph

Manage your Laravel app as if it was a CMS – edit any text on any page or in any email without touching Blade or language files.

Visit Paragraph
Laravel Forge logo

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Lucky Media logo

Lucky Media

Bespoke software solutions built for your business. We ♥ Laravel

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
LaraJobs logo

LaraJobs

The official Laravel job board

LaraJobs
Larafast: Laravel SaaS Starter Kit logo

Larafast: Laravel SaaS Starter Kit

Larafast is a Laravel SaaS Starter Kit with ready-to-go features for Payments, Auth, Admin, Blog, SEO, and beautiful themes. Available with VILT and TALL stacks.

Larafast: Laravel SaaS Starter Kit
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Rector logo

Rector

Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies

Rector

The latest

View all →
Anonymous Event Broadcasting in Laravel 11.5 image

Anonymous Event Broadcasting in Laravel 11.5

Read article
Microsoft Clarity Integration for Laravel image

Microsoft Clarity Integration for Laravel

Read article
Apply Dynamic Filters to Eloquent Models with the Filterable Package image

Apply Dynamic Filters to Eloquent Models with the Filterable Package

Read article
Property Hooks Get Closer to Becoming a Reality in PHP 8.4 image

Property Hooks Get Closer to Becoming a Reality in PHP 8.4

Read article
Asserting Exceptions in Laravel Tests image

Asserting Exceptions in Laravel Tests

Read article
Reversible Form Prompts and a New Exceptions Facade in Laravel 11.4 image

Reversible Form Prompts and a New Exceptions Facade in Laravel 11.4

Read article