Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

davy_yg's avatar
Level 27

Two Languages

Hello,

I want to make a website with two languages. My plan is to have a form with two tabs. One for English and the other one for Indonesian.

Then in the database I want to split the table into two tables (for example: service_id dan service_en) for each table with the same meaning.

Then, will it be possible just by pressing one flag click on the front page, it will be automatically select the correct language ?

Which means it automatically knows which table to select?

0 likes
13 replies
aurawindsurfing's avatar

Hey @davy_yg

What you are looking for is called localization. There are many tutorial about it. But they key points are:

  1. App uses locale to figure out what language it needs to display to user.
  2. Use this guide to start with: https://laravel.com/docs/master/localization
  3. It is not as simple as in the docs as you soon find out you gonna need more.

In your case you need to translate your model and instead of normal fields use json fields in your table. That json field will then consist of as many translations as you like. You can use for it: https://github.com/spatie/laravel-translatable or https://github.com/ARCANEDEV/Localization/blob/master/_docs/3-Usage.md#translated-models

Here is list of additional stuff I'm using for my localizations:

https://github.com/ARCANEDEV/Localization Really good staring point, allows you also to localize your routes wich in turn is important for SEO.

https://github.com/cviebrock/eloquent-sluggable Once your routes are localized you also need to localize your models as for SEO it is not good to use model id in the paths.

https://github.com/rmariuzzo/Laravel-JS-Localization Solves a possible problem of making your translations available inside Vue, jQuery etc

Last but not least here is a paid service that you might use while your app grows big and you realise that you need to add multiple languages: https://poeditor.com/ it allows for community to translate your app into multiple languages.

Here is a good example how this is used in real life:

https://help.crisp.chat/en/article/what-languages-are-supported-by-crisp-1ivdmy2/ https://poeditor.com/join/project/l718IiBWl8

I hope this answers your question! As you can see it is hard to think about it while you deal with 2 languages but if as in crisp you deal with dozen of languages it changes your thinking of how app should be structured from the very start.

Hope it helps!

Tray2's avatar

That is in my opinion the wrong way to go, both database wise and applicationwise.

There should only be one table for services you can however add a field that tells which language it belongs to.

You should use locale to handle the different languages.

https://laravel.com/docs/7.x/localization#introduction

davy_yg's avatar
Level 27

@tray2

one more column for lang. So whenever I select id (Indonesian) --> I can retrieve the lang selection, using lang localization to select all the content from the selected language.

That's the logic right?

davy_yg's avatar
Level 27

@aurawindsurfing thx for advice. I think as of now, I prefer not to use the package yet, as it is confusing. I tried it before.

if using language localization and selecting the language by querying the language directly after retrieving the lang, I think I prefer that way.

aurawindsurfing's avatar

@davy_yg

I get the point. However you will find out soon that especially where you have models that need to be translated there is no easy way. You either embrace and think it through while building your app or suffer later ;-)

davy_yg's avatar
Level 27

@aurawindsurfing

If I am using the package what about the table? I am a little confuse about how to create the table. Since edit feature only passed one id number - If I have two languages then I will requires two id (one for English and one for Indonesian).

Any idea how to solve this issue?

Tray2's avatar

There are several ways to do that.

You can have this table structure

  • id
  • field_en
  • field_in

Or you can have something like this

  • id
  • common_id
  • language
  • field

In the first example a record could look like this

id * field_en * field_in
*************************
1  *  Thank you * Terima kasih

In the second it could look something like this

id * common_id * language * field
*****************************
1 * 1 * en * Thank you 
2 * 1 * in * Terima kasih

The common id can be something more descriptive as well something along the línes of

  • thank_you_message
  • create_post_successfull

You can of course but all the languages in another table and reference then with just a foreign key. It all depends on how many records you need to create in your table.

davy_yg's avatar
Level 27

Can you write this in the view:

@if (App::isLocale('en')) {

	$content->thank_you;
} @else {

	$content->terima_kasih;
}
piljac1's avatar

@tray2 I personally use the first approach you mentioned with a tweak.

Let's say I have an item name, my website main language is fr and en is also supported, I will have a name column and a name_en column. The non-suffixed column represents the app default locale, which also acts as a fallback.

I also have a LocalizableModel class which extends Model and has one function, which is getLocalized. The function receives the non-suffixed column name as a param and tries to get the field in the current app locale. If the retrieved value is empty, fallback to the default local string.

$item->getLocalized('name')
aurawindsurfing's avatar

@davy_yg

No this is not correct. You will have only one id when locale is en and it has translation it will show that translation, if locale is in then it will look in the same column for indonesian translation and display one if it exists, if not it will fall back to the default translation.

You need to change your migration so your column will be:

$table->json('field');

Then the table will look like this:

id * field
*************************
1  *  {"in":"Terima kasih","en":"Thank you"} 

The beauty of this solution is that it is ready for adding as many languages as you like without changing your database. You also do not need to change your code, by default it will just look for translation for that locale and if it does not exist it will fall back to the default one.

Example from the docs: https://github.com/spatie/laravel-translatable

$newsItem = new NewsItem; // This is an Eloquent model
$newsItem
   ->setTranslation('field', 'en', 'Thank you')
   ->setTranslation('field', 'in', 'Terima kasih')
   ->save();
   
$newsItem->field; // Returns 'Thank you' given that the current app locale is 'en'
$newsItem->getTranslation('field', 'in'); // returns 'Terima kasih'

app()->setLocale('in');

$newsItem->field; // Returns 'Terima kasih'
asathler's avatar

Hi folks

Like @aurawindsurfing said:

"It is not as simple as in the docs as you soon find out"

However, it's not that complicated either!

@Tray2 also has a point:

"That is in my opinion the wrong way to go, both database wise and applicationwise".

Then, I suggest you start reading, as already suggested, https://laravel.com/docs/master/localization.

But, learning by example it's more helpful. So:

  • Create a new fresh laravel project (just for tests) - if you need it;
  • Using your IDE, create a new folder for Indonesian translations - /resources/lang/id, I suppose.
  • Create a new file msgs.php in /resources/lang/en/msgs.php with this
<?php

return [
    'docs' => 'Docs',
    'news' => 'News',
];
  • Now, lets create another on file in /resources/lang/id/msgs.php with this code
<?php

return [
    'docs' => 'Dokumen',
    'news' => 'Berita',
];

  • Next, lets make 2 changes in /resources/views/welcome.blade.php for only this strings (lines 88 and 90)
<a href="https://laravel.com/docs">Docs</a>
<a href="https://laravel-news.com">News</a>

to this

<a href="https://laravel.com/docs"> {{ __('msgs.docs') }} </a>
<a href="https://laravel-news.com"> {{ __('msgs.news') }} </a>
  • At last, we need to change your locale in /config/app.php to Indonesian.
    'locale' => 'en',

to this

    'locale' => 'id',
  • Start your local server with
php artisan serve
  • See your welcome page, with this two links translated, in your favorite browser

Magic helper

All dirt job is done by laravel helper function for translations!

{{ __('msgs.docs') }}
  • msgs is the translation files; and
  • docs is the key of array with word or phrase you translate in each language file.

And to use this satisfactorily you need to have translations files (msgs or so) for each language you wanted.

Of course, to add another language, you have create other folders in /resources/lang (like fr, to french; es to spanish; pt-br to brazilian portuguese; for examples) and use the same file name for news translations.

Keep in mind, although you may have multiple files for translations, in my opinion, it's made more difficult to maintain in large projects.

For table uses like your original request

Yes, you can change the column in use passing the column name plus locale option as variable.

$columnTranslated = 'service_' . config('app.locale');
echo $table->$columnTranslated;

Later, you may modify your project to looking for a user config instead of /config.app.php locale or yet with a uri parameter option.

Hope this helps.

1 like

Please or to participate in this conversation.