Appearance
Localization
- Laravel's localization features provide a convenient way to retrieve strings in various languages, allowing you to easily support multiple languages within your application.
- Language strings are stored in files within the lang directory in the root of your application (nit visible by default)/ Within this directory there should be a subdirectory for each language supported by the application.
- Here you see the default (English) views for the error 404-page page and the registration page:
- All these pages can easily be translated to another language, for example Dutch
Single language site (other than English)
WARNING
- It's best to install the translation files immediately after creating a new Laravel project
- If you already have a project, you can update your project with the command
composer update
and then install the translation files
Publish the language files
- Publish the language files with the command:
bash
php artisan lang:publish
php artisan lang:publish
1
- Now you can find the language files in the lang directory in the root of your application
Install the additional language files
- There is a really nice package called Laravel-lang that provides a lot of translation language files for Laravel, Jetstream and all the other packages maintained by the Laravel team
- Install this package, together with the Laravel Lang Publisher Package, with the following command:
bash
composer require laravel-lang/lang laravel-lang/publisher laravel-lang/attributes --dev
composer require laravel-lang/lang laravel-lang/publisher laravel-lang/attributes --dev
1
- Next, publish the language file(s) you want to use with the following command:
(choose nl for Dutch, fr for French, etc.
bash
php artisan lang:add nl
php artisan lang:add nl
1
- Most of the Dutch language files are now installed in the lang/nl directory and there is one extra lang/nl.json file
Set the default language to Dutch
- Open the config/app.php file, search for the locale key and set the value to nl
php
...
'locale' => 'nl', // change from 'en' to 'nl'
...
'fallback_locale' => 'en',
...
...
'locale' => 'nl', // change from 'en' to 'nl'
...
'fallback_locale' => 'en',
...
1
2
3
4
5
2
3
4
5
- Reload the 404-page and the registration page, and you will see that the pages are now in Dutch
How does it work?
- Translatable items are always surrounded with
__()
and contain:- The default string value, in case the translation string is not found in the
lang/language.json
file (lang/nl.json
in our case - The name of the language file (before the dot) followed by the key inside the language file (after the dot)
- The default string value, in case the translation string is not found in the
Translating a strings
- Open the resources/views/errors/404.blade.php file
- The title of the page and the message are surrounded with
__('Not Found')
php
@extends('errors::minimal')
@section('title', __('Not Found'))
@section('code', '404')
@section('message', __('Not Found'))
@push('script')
<script>
// remove the last div inside the nav tag
document.querySelector('header nav div:last-child').remove();
</script>
@endpush
@extends('errors::minimal')
@section('title', __('Not Found'))
@section('code', '404')
@section('message', __('Not Found'))
@push('script')
<script>
// remove the last div inside the nav tag
document.querySelector('header nav div:last-child').remove();
</script>
@endpush
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Translation arrays
- Static text translations are (mostly) stored in the lang/nl.json file, but other translations (validation messages, auth, ...) are stored in the lang/nl/xxxxx.php file
- Let's go to the shop page, and make the page very small (so you can see the 'Previous' and 'Next' buttons)
- set the default language to English (
'locale' => 'en'
))
- Now open the Livewire component resources/views/vendor/livewire/tailwind.blade.php file that we published and modified earlier in this course
php
<nav role="navigation" aria-label="Pagination Navigation" class="flex items-center justify-between">
<div class="flex justify-between flex-1 sm:hidden">
<span>
@if ($paginator->onFirstPage())
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md select-none">
{!! __('pagination.previous') !!}
</span>
@else
<button type="button" wire:click="previousPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}.before" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
{!! __('pagination.previous') !!}
</button>
@endif
</span>
<span>
@if ($paginator->hasMorePages())
<button type="button" wire:click="nextPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}.before" class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
{!! __('pagination.next') !!}
</button>
@else
<span class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md select-none">
{!! __('pagination.next') !!}
</span>
@endif
</span>
</div>
...
</nav>
<nav role="navigation" aria-label="Pagination Navigation" class="flex items-center justify-between">
<div class="flex justify-between flex-1 sm:hidden">
<span>
@if ($paginator->onFirstPage())
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md select-none">
{!! __('pagination.previous') !!}
</span>
@else
<button type="button" wire:click="previousPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" dusk="previousPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}.before" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
{!! __('pagination.previous') !!}
</button>
@endif
</span>
<span>
@if ($paginator->hasMorePages())
<button type="button" wire:click="nextPage('{{ $paginator->getPageName() }}')" wire:loading.attr="disabled" dusk="nextPage{{ $paginator->getPageName() == 'page' ? '' : '.' . $paginator->getPageName() }}.before" class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
{!! __('pagination.next') !!}
</button>
@else
<span class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md select-none">
{!! __('pagination.next') !!}
</span>
@endif
</span>
</div>
...
</nav>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- Look at the translation string
__('pagination.previous')
and__('pagination.next')
pagination
(before the dot) refers to the name of the language fileprevious
andnext
(after the dot) refers to the key inside that language file
php
<?php
return [
'previous' => '« Previous',
'next' => 'Next »',
];
<?php
return [
'previous' => '« Previous',
'next' => 'Next »',
];
1
2
3
4
5
6
2
3
4
5
6