InertiaJS & Laravel misc
Handling translations in Laravel and InertiaJS applications
Determining active routes05:24
Create a searchable list09:05
Handling regular forms16:41
Inline forms validation09:15
Infinite scrolling with InertiaJs and Laravel15:57
Notifications with Laravel Echo and Pusher in InertiaJS applications (part one)14:47
Realtime Notifications with Laravel Echo and Pusher in InertiaJS applications (part two)09:07
Building a user following / unfollowing system with Laravel and InertiaJS22:39
Changing button labels on hover and InertiaJS progress indicators05:34
Building the home feed and infinite scroll component with Laravel and InertiaJS17:52
Building a form component to post new tweets with Laravel and InertiaJS19:38
Media attachments with Laravel and InertiaJS41:46
Avatar image input component with VueJS, Inertia, and Tailwind CSS14:44
Bugfixing the avatar input component04:16
New InertiaJs form helper - less boilerplate, more awesomeness08:30
InertiaJS scroll management13:34
InertiaJS submitting form arrays and error handling11:46
Create a searchable select field with InertiaJS and vue multiselect13:10
InertiaJS data evaluation in Laravel and VueJS applications04:37
Creating a datatable with Laravel and InertiaJS10:58
Customize the default Jetstream view responses in Laravel apps using the Inertia stack03:46
Fuzzy searching with Fuse.js in Laravel & InertiaJS applications10:38
Handling translations in Laravel and InertiaJS applications12:24
Replace auth redirect with modal dialog in InertiaJS & Laravel applications06:49
Handling translations in Laravel and InertiaJS applications
[00:52] One place to share the translations would be inside the handle inertia request middleware, here under this share method. However, these props are sent with each and every request, and I wouldn't want to put something that rarely changes in here. Another alternative would be to create a blade component and use it inside our main app.blade layout. So let's do it.
[01:14] We can create a new blade component by opening the terminal,and typing
php artisan make:component and then the component name, in our case, Translations. This will create a php class under app, view, components. Here it is, and the corresponding blade view, which we can find under resources views components, and here it is.
[02:26] To check that everything is working, we can open our app.blade file and use the new component. All blade component tags start with an x, dash, and then the name of the component class, in our case, translations. Now we can go in the browser and view the page source, and here it is. We solved problem number two, which was sharing the translations with the frontend. Let's start working on number one, which is collecting the translation strings.
[02:59] Back to the component class, this translations array will be a combination between the php translations and the json translations. The php translations are the strings coming from the php files, while the json translations come from the language.json file, for example en.json. Usually I put all my translations inside the json files.
[03:30] To load the correct translations, we need to know the locale. We can grab that by calling app, and we'll use the facade, get locale. We can now use the locale to check if the language directory exists. We can do if file, and we'll use the facade, exists, resource path lang slash local. So this will check if this en directory exists. To grab all the files inside the language directory, we can do file all files resource path lang local. Now, this will return us an array of files, and we can put those files in a collection and then map through it.
[04:18] To grab the translation strings, we'll do collect, and then filter, because we only wanted the php files, and we can filter them using filter, and then return file get extension equals equals php, and this will make sure we only get the php files. Then we can do flat map, and the reason we are using flat map is because whenever we are parsing a php file the end result is an array, so we'll have an array of arrays. And we actually need an array of strings like these ones. To get the output of the php file we can do file, and we'll use the facade, get require and then the file path file get real path.
[05:18] So this will basically execute this file and get the outputs. However, some translation files contain nested arrays; like this validation.php file, for example. We can flatten those by using the Arr class, specifically the dot method. So we can do Arr dot, and then pass in the array. And of course we need to return this. Finally, we need to transform this collection into an array, so we'll call the to array method and assign it to the php translations variable.
[05:55] Moving on to the json translations we'll do pretty much the same thing. We'll check if the file exists, so if file exists resource path lang slash local.json, and then to get the file contents we can do file get and pass in the path, but we'll want these to be an associative array, so we'll have to do json decode, pass in the contents and true as the second argument.
[07:48] Now, to find the translation we can do let translation equals window dot underscore translations of key and set the key as default just in case we don't find the translation. To test this out, let's register the mixin in app.js. So I'll go here and do import translations from mixin's translations, and then down here we can do mixin, and pass in translations. Let's open the dashboard page for example, and try to translate this header. And now I'll go to the en.json file and say dashboard equals welcome.
[08:43] Now if I go into browser and refresh, we have welcome instead of dashboard. But what if I want to pass it parameters like, let's say, name, and do something like name equals page props user name. If I go back in the browser and refresh, it will say dashboard column name. That's because this translation doesn't exist yet, so let's update it and say welcome column name, and if I go now in the browser and refresh, it says welcome column name. But we need to replace this with the currently authenticated username, so we'll need to go to translations and figure out how to make these replacements.
[09:36] We can start by grabbing the object keys using object.keys of replacements, and then loop through them. Let's say r from replacement and then translation equals translation replace, and we'll do column whatever r is, and then replacements of r. Let's give it a go. I'll go in the browser and refresh, and here it is: welcome dr daphne hurt a phd whatever. So that works.
[10:08] One last thing we could do is to cache the translations just so we don't parse the language files with every request. So I'll go inside the translations class and down here we'll do translations equals Cacche and I'll use the facade, remember forever, let's say translations underscore locale, then function, and we'll need the locale, so I'll do use locale and then grab all this, put it here, and return the translations.
[10:52] Now if I go in the browser and refresh, everything is still working. However, you do need to keep in mind that you'll have to clear the cache whenever you change the translations. So, for example, if I remove this, save, go to the browser and refresh, the translations are still there. So you need to do
php artisan cache:clear, and now if I refresh again, the translations have been recompiled. So do that again, cache clear, refresh, here they are.
[11:28] And that's how I handle translations in inertia.js applications these days. One last secret I will show you is how to do this without losing your mind over missing translations. What I typically do is, I make sure to always use the translation method. So everywhere there's static text, there's a translation method being used. Then I install a small package I wrote called
druc/laravel-langscanner, so I do
composer require druc/laravel-langscanner, and then whenever I need to translate the application in a different language, I can just do
php artisan langscanner nl, and passing the locale let's say nl for netherlands. And now, if I go on under languages, here is nl.json, with all the translation strings. And then I just pass this file to the client, they fill it in, send it back, and that's it.