How to Create a Dynamic Multi-Language Website in Laravel 10

Multi-language website is trendy as it presents the web page in different languages. Users can choose the language and the website can display information in the chosen language. Laravel provides an easy way to implement multi-language for a website, it is called Laravel Localization.

In this topic, we will develop a Laravel 10 application that can work for multiple languages. Users can choose the language from a dropdown list and data will be displayed in the selected language. We will make it dynamic by storing Language names and other data in a MySQL table in multiple languages.

Multi-language in Laravel Laravel localization

Download Source code from github.

How to setup Laravel Localization

Before we move on to developing this application, let us look at what Laravel 10 provides us for multiple language implementations. Laravel 10 provides easy ways to retrieve strings for various languages using translation files for each language. It uses language files for each language under the 'lang' folder within the Laravel project. By default, Laravel 10 does not provide the 'lang' directory. We need to use the below artisan command to publish it.

Once this is done, we will have a 'lang\en' folder in the project root. Laravel provides language files for English(en) language by default. If we add another language, a folder with the name as the language code under the 'lang' directory should be created. For example, if we add French (fr), we should have a folder 'lang\fr' and all the translation files related to the French language should be placed under it.

Application's default language is set in config\app.php file. There you will see Localization parameters as below:

You can change the default language for a http request by using App::setLocale($locale); where $locale is the language code.

How to Create Laravel Translation File

A translation file is a .php file with key=>value pairs for translations. For example, for the French language, we can have a messages.php under the 'lang\fr' directory. As an example, the contents of the file can be as given below:

For English (lang\en\messages.php)

For French (lang\fr\messages.php)

Only the right side (values) will be different for different languages, left side (keys) will remain the same. In the code (views and controller etc.).

There is another way to create the translation files. these are JSON files. In that case, each language will have a JSON file under the 'lang' directory, like en.json, fr.json, etc. In this topic, we will use only the first approach which uses the php files for translations.

How to Retrieve Translations

To use the translations on a web page, we will use the keys from the translation files; values will automatically be displayed by Laravel. For example, if we want to display the title of a page, we will use the below line for the web page title in html.

We can also use trans() function to get the translated values.

In case a translation key does not exist, it will return the given key. Hope, by now you have an idea on how to setup Laravel Localization for different Languages. Now, we will develop a multi-language website using Laravel 10 with MySQL database.

Develop a Multi-Language Website in Laravel 10

We will develop a website using Laravel Localization. We will store the Languages in a MySQL table using a form and also display data in the Language selected by the user. This will be dynamic because, for a new Language, we do not need to change our code; only the Language translation files are to be created for the newly added Language.

What are we going to do?

  1. Create Laravel Project and Migration: We will create a Laravel 10 project. We will create migrations for three custom tables, these are 'languages', 'categories' and 'category_translations'. The 'languages' table will store different Languages and 'categories' and 'category_translations' will store Product Categories with translated data for multiple Languages. We will add/update Languages and Categories using the forms. 'category_translations' will be used to store category names and descriptions for each category and each Language.
  2. Setup Laravel Localization: We will publish Laravel Language files. We will set up Laravel Localization so that our website can work for multiple languages.
  3. Create a Top Menu and a form to add/update Languages: The Top Menu will have menu items for maintaining Languages and Categories. Also, it will display a list of active Languages in a dropdown. We will add English(en), French(fr) and Hindi(hi).
  4. Create a form to add/update product categories in multiple Languages: This form will have multiple tabs for different Languages so that we can enter category names and descriptions in multiple Languages and submit the form.
  5. Add more Languages without changing any code: Finally, we will add more Languages and create translate files. We do not have to change our code for a new language, only we will have to create the translation files for that Language.

Let's start working on the project.

Create Laravel Project and Migration

Let us create a project in Laravel 10. Make sure you have Composer and PHP installed in your system. We will use the below command to create the project, our project name is lara_lang.

This will create a folder named "lara_lang" under the folder where you run the above command.

Create a database named 'lara_lang' in MySQL and update .env file for database details. Update the file as below:

We will create three custom tables

  1. Table: LANGUAGES

    This table will store all Languages. Along with name and code, it will have a status column to make a Language Active/Inactive. Using a form, we will add and update Languages.

  2. Table: CATEGORIES

    1. This table will store all product categories. All non-translatable fields can be stored in this table. In our case, we will have only the ID column in this table. Translatable fields such as category name and description will be stored in a translate table as described next.

  3. Table: CATEGORY_TRANSLATIONS

    This table is the translation table for all categories. It will store category names and descriptions in different Languages. It will have Category ID and Language Code as the foreign keys.

Let us create the migrations for these tables. Go to your project folder and run the below command to create migration for Languages using the VS code terminal.

Create Language Model with migration

Create Category Model with migration

Create CategoryTranslation Model with migration

Above three commands will create the migration files as given below:

<yyyy_mm_dd_xxxxxx>_create_languages_table.php
<yyyy_mm_dd_xxxxxx>_create_categories_table.php
<yyyy_mm_dd_xxxxxx>_create_category_translations_table.php
They will be created under the database/migrations folder. The three models, named "Language", "Category" and CategoryTranslation will be created under app/Models folder. Here yyyy_mm_dd_xxxxxx is the datetime when the migration files were created.

Open each migration file and Update the up() methods as below:

Migration scripts for 'languages' table

Language code is unique, example, 'en' (English), 'fr'(French), 'es'(Spanish), 'ar'(Arabic), 'hi'(Hindi).

Migration scripts for categories table

We are not adding any columns here, we are keeping only default columns. You can add only non-translatable columns in this table. Translatable columns should be placed in the translate table which is given next.

Migration scripts for category_translations table

This translation table will store category names and descriptions in various Languages. category_id and language_code are the foreign keys.

Let us now run the Laravel migration to create the new tables as well as the default tables for Laravel. Run the below command from the project folder to create the tables:

After running the migration, the below tables will be created, our custom tables are marked.

laravel migration for multi-languages

Update the Models

Let us update the models to add $fillable columns and the relationship function wherever applicable.

Model Language
Model Category

There is a hasMany relationship between Category and CategoryTranslation, we will use this function whenever we want to retrieve category details.

Model CategoryTranslation

Setup Laravel Localization

We need to publish Laravel's Language files by using the artisan command. Run the below command from the terminal to create the 'lang' directory and the default language files.

This will create the 'lang\en' directory with the laravel supplied files for English as below :

Multi-language website in Laravel

There are two localization parameters defined in config/app.php file. These are 'locale' and 'fallback_locale' and they are set as 'en' (English).

Now, we will create our translation file for the website under the 'lang/en' directory, let us give the name of the file as site.php. As of now, we will create only for English, later when we add more languages, we will create site.php for each Language.

Let us just write the title of the website in this file, for the time being:

lang/en/site.php

Create a Top Menu and a form to add/update Languages

We will create a Top Menu with a dropdown to show the list of Languages. Also, we will develop a form to add/update Languages.

To set the current Language in the Session or App locale we will use a middleware. All the routes will go through this middleware. Our menu will look like below:

Multi-language website in Laravel

Create a middleware to set the Language.

Create LanguageMiddleware using below command:

This middleware will set the current language from the session to App locale. It will also share the current Language and list of all other active Languages using view share. So that we can use them in the menu. Let's see the code for the middleware:

app/Http/Middleware/LanguageMiddleware.php

We are setting the Session locale from App locale if the Session locale is not set. Otherwise, we are setting App local from the Session. Then we are getting the current Language details from the Language model using the Session locale. Also, we are getting a list of all Languages other than the current Language to use in the dropdown. These are all required in our view, that is why we are using view::share here.

Update Kernel.php to add the Middleware alias.

Create Controllers

We will create two controllers - one for Home page and other a resource controller to add/update Languages.

HomeController Methods

The method setLanguage() will set the selected Language in Session and App locale. This function is called when a user selects a Language from the dropdown.

app/Http/Controllers/HomeController.php

LanguageController Methods

LanguageController is used to add and update Languages using the Language model. There will be standard methods that will be used here - create(), store(), edit() and update(). These are usual methods for add and update using a resource controller. I am not going to explain in detail about these methods. The only change we have to make here is that whenever we want to show any message we have to use translate files. Our language file is lang/en/site.php, so we will update this as per the requirement. See the below methods:

app/Http/Controllers/LanguageController.php

You can see we are not writing the actual messages, but we are using keys defined in the translate file site.php which is given below:

lang/en/site.php

These are all key=>value pairs. For another language you have to translate the values (right part) in that language, keys (left part) will remain the same.

Update Routes

We will create one route for the home page, one for setting the locale when the user selects Language from the dropdown and a resource route to add/update Languages. All these routes should go through the LanguageMiddleware.

routes/web.php

Views

Below are the views for the menu and add/edit forms including the layouts. We have created directory 'layouts' and 'language' under 'views'. In all the views we will use translated values.

resources/views/layouts/header.blade.php

See in line 2, we are using app()->getLocale() for the language. '_' is normally used for regions. For example, if en_GB or en_US is defined in App locale, we need to change '_' (underscore) to '-' (hyphen) here.

resources/views/layouts/footer.blade.php

resources/views/layouts/top_menu.blade.php

Check the menu items, these are home, languages, categories and at the end currently selected language is displayed with a dropdown to show all other active Languages. Note that the current Language ($clang in line 23) and the $languages used in the for-loop are shared by the middleware using view share as shown earlier.

resources/views/layouts/master.blade.php

View to display list of Languages from the database

Laravel 10 dynamic multi-language website

Index view to show the above list of Languages is given below:

resources/views/language/index.blade.php

Note that h1, h2 and table header are all coming from the translate files. Also, note that the Edit button is disabled for the current Language. This is done to make sure, the current language is not updated as inactive.

View to add/update Language

We will be using the same view to add and update Languages. You can read the topic How to Use the Same Form for Add and Edit in Laravel

add languages in database for Multi-language in Laravel 10

resources/views/language/add_language.blade.php

Form fields, labels, names and placeholders are taken from the translate file. Since we are using the same form for Add and Update, separate routes are used for the form action.

Here is the stylesheet:

public/css/style.css

Let us now start the server to add Languages using the Add form.

Run localhost:8000 in the browser, we will see the below screen.

Build a dynamic Multi-language website in Laravel

We have not added any Languages in the Language table. The Language dropdown will be empty and we do not see the current Language. Now click on the Maintain Languages and add Language English (en). See below:

Multi-language in Laravel add language form
Localization Implementation in Laravel with Language

After submitting the form, we will see the below screen. You can now see English is displayed, but the dropdown is empty. So, we will add another Language French.

Laravel 10 Tutorial - Localization

Add French, use Google Translate to translate from one Language to another.

Laravel translation files

If you submit, you will see the dropdown showing the French language and it is also added to the list. We cannot use French as of now, since we have not added French to the Laravel 'lang' directory. So, create a directory 'fr' under 'lang' and copy site.php from 'en' dorectory and paste it into 'fr' directory. Now you will have to just get the translated values for French in the site.php. Using Google Translate we can replace English texts with corresponding French translated texts.

Once that is done, we will have below site.php under 'lang/fr' directory.

If we now refresh the page and select French, you will see the below screen:

laravel localization tutorial

You can see all the texts are translated into the French Language. If you select English, it will display all in English.

Now you can add more Languages and create the translate files for each language in a separate directory under the 'lang' directory. You can update the Languages and make it Inactive. Only active languages will be shown in the dropdown.

I have added Hindi and created the translate file in lang\hi\site.php. See below:

Change app default locale dynamically

Create a form to add/update product categories in multiple Languages

Now we will create a form where we can add data in multiple Languages. So, if there are 3 active Languages, data will be stored in 3 Languages in the database. Our Category and CategoryTranslation models are created for that.

Maintaining Languages and product categories are Admin jobs, but users can view the product categories on the website. So, the admin has to enter the data in all supported Languages for the website.

Add Category form will have separate tabs for each Language, it will be created dynamically and all translatable fields will be under each tab. See below:

Using a database for localization in Laravel

We will create a resource controller named CategoryController, add a resource route for the category and create an add/edit form. Add this route in web.php within the middleware.

Resource route for category

CategoryController

Method index()

Since we have a one-to-many relationship between Category and CategoryTranslation we will use the cat_translation() function defined in the Category Model. This will give all categories with names and descriptions for the current Language.

Add/Edit form for categories

Our add category form will look like below.

Laravel 10 How To Create Multi Language Website Tutorial

You can see there are multiple tabs for languages to enter category names and descriptions. So, we need to send all active languages to the view. We will also assume that English is the default language, so the active tab will be for English. In the controller, we will define a variable for the active Language, see the below code:

We are sending a list of active Languages and the active Language to the add_category view.

CategoryController store() method

Note that the category name and description are the arrays in the form and are created dynamically, so after the form is submitted a single row is to be inserted in the Category Model and multiple rows (one row for each language code) are to be inserted in the CategoryTranslation model.

You can see a row is inserted in Category Model and using a loop multiple rows are inserted in CategoryTranslation. Note that we are displaying success and error messages from the language files.

CategoryController edit() method

We have to get the details of the category along with the translations. Then we will use two arrays, one for the category name and the other for the description using the language code as the array keys.

CategoryController update() method

update() method will be similar to store method, except we will use updateOrCreate() instead of create() method on the CategoryTranslation model. Here, only the translate table will be updated.

View to display the list of categories

In this view, we will display all categories in an html table. We will display the name and description with an Edit button for each row. Note that we have to use Language files for all the texts. Below is the blade file:

resources/views/category/index.blade.php

View to add/update category

We will be using the same form for add/edit category.

resources/views/category/add_category.blade.php

We are dynamically creating the tabs for each Language and displaying the values in each tab for each Language code for editing. Note that the name and description are the arrays with Language code as the keys.

Now you can add product categories in multiple Languages and also can update them. I have added a few categories which are displayed in different Languages as given below:

set up multiple languages for your web app

In French

create a multilingual project in Laravel 10

In Hindi

Building a multilingual site with Laravel Localization

Add more Languages without changing any code

You can add more Languages, like Arabic (ar), Spanish(es), Bengali (bn) and create site.php for these Languages. The application will work without modifying any code.

I added three more languages and created the site.php for each language. Add category form now shows more tabs as given below:

Managing Multilingual Content in Laravel

Our project is done, hope this topic was helpful for you.

Download Source code from github.

Conclusion

In this topic we have covered three areas about Laravel Localization:

  • We have discussed how to setup Laravel Localization for Language Translation.
  • Then we have developed a form to add/update Languages in the database for a dynamic multi-language website.
  • Then we have developed a form to add/update product categories in multiple languages in the database. Also, we have seen how to display the data in multiple languages.