User-Specific Language Dropdown with Country Flags
This guide will walk you through implementing a user-specific language dropdown with real country flags that allows each user to set their own language preference, saves it to the database, and applies it across the entire application.
Overviewβ
The language dropdown provides:
- Real country flag icons for each language
- User-specific language preferences stored in database
- Automatic language switching across the entire application
- Persistent language settings across login sessions
- Clean, responsive design
Prerequisitesβ
- Laravel application with user authentication
- Existing translation files in
lang/
directory - User table with language field
- Basic understanding of Laravel middleware and localization
Step 1: Update Language Constantsβ
First, update your language constants to include country flag codes.
File: config/constants.php
β
'langs' => [
'en' => ['full_name' => 'English', 'short_name' => 'English', 'flag_code' => 'us'],
'es' => ['full_name' => 'Spanish - EspaΓ±ol', 'short_name' => 'Spanish', 'flag_code' => 'es'],
'sq' => ['full_name' => 'Albanian - Shqip', 'short_name' => 'Albanian', 'flag_code' => 'al'],
'hi' => ['full_name' => 'Hindi - ΰ€Ήΰ€Ώΰ€ΰ€¦ΰ₯', 'short_name' => 'Hindi', 'flag_code' => 'in'],
'nl' => ['full_name' => 'Dutch', 'short_name' => 'Dutch', 'flag_code' => 'nl'],
'fr' => ['full_name' => 'French - FranΓ§ais', 'short_name' => 'French', 'flag_code' => 'fr'],
'de' => ['full_name' => 'German - Deutsch', 'short_name' => 'German', 'flag_code' => 'de'],
'ar' => ['full_name' => 'Arabic - Ψ§ΩΨΉΩΨ±ΩΨ¨ΩΩΩΩΨ©', 'short_name' => 'Arabic', 'flag_code' => 'sa'],
'tr' => ['full_name' => 'Turkish - TΓΌrkΓ§e', 'short_name' => 'Turkish', 'flag_code' => 'tr'],
'id' => ['full_name' => 'Indonesian', 'short_name' => 'Indonesian', 'flag_code' => 'id'],
'ps' => ['full_name' => 'Pashto', 'short_name' => 'Pashto', 'flag_code' => 'af'],
'pt' => ['full_name' => 'Portuguese', 'short_name' => 'Portuguese', 'flag_code' => 'pt'],
'vi' => ['full_name' => 'Vietnamese', 'short_name' => 'Vietnamese', 'flag_code' => 'vn'],
'ce' => ['full_name' => 'Chinese', 'short_name' => 'Chinese', 'flag_code' => 'cn'],
'ro' => ['full_name' => 'Romanian', 'short_name' => 'Romanian', 'flag_code' => 'ro'],
'lo' => ['full_name' => 'Lao', 'short_name' => 'Lao', 'flag_code' => 'la'],
'bn' => ['full_name' => 'Bengali', 'short_name' => 'Bengali', 'flag_code' => 'bd'],
],
Step 2: Add Flag Icons CSSβ
Add the Flag Icons CSS library to your layout.
File: resources/views/layouts/partials/css.blade.php
β
<!-- Flag Icons CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icons/7.2.3/css/flag-icons.min.css" integrity="sha512-bZBu2H0+FGFz/stDN/L0k8J0G8qVsAL0ht1qg5kTwtAheiXwiRKyCq1frwfbSFSJN3jooR5kauE0YjtPzhZtJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<style>
.fi {
width: 1.2em;
height: 0.9em;
border-radius: 0.125rem;
display: inline-block;
vertical-align: middle;
}
</style>
Step 3: Create User Locale Middlewareβ
Create middleware to automatically set the application locale based on the authenticated user's language preference.
Generate Middlewareβ
php artisan make:middleware SetUserLocale
File: app/Http/Middleware/SetUserLocale.php
β
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\App;
use Carbon\Carbon; // Add this import
class SetUserLocale
{
public function handle(Request $request, Closure $next)
{
// Check if user is authenticated
if (Auth::check()) {
$user = Auth::user();
// Get user's language preference, default to 'en' if not set
$userLanguage = $user->language ?? 'en';
// Validate that the language exists in available languages
$availableLanguages = array_keys(config('constants.langs', []));
if (in_array($userLanguage, $availableLanguages)) {
// Set application locale for UI translations
App::setLocale($userLanguage);
// Set session locale for consistency
session(['locale' => $userLanguage, 'user.language' => $userLanguage]);
}
}
// CRITICAL: Always keep Carbon in English for date operations
// This prevents "Trailing data" errors in charts and date parsing
Carbon::setLocale('en');
return $next($request);
}
}
Step 4: Register Middlewareβ
Register the middleware in your HTTP Kernel.
File: app/Http/Kernel.php
β
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\SetUserLocale::class, // Add this line
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
Step 5: Add Controller Methodβ
Add a method to handle language updates in your user management controller.
File: app/Http/Controllers/ManageUserController.php
β
/**
* Update the current user's language preference
*/
public function updateLanguage(Request $request)
{
try {
$user = Auth::user();
$language = $request->input('language');
// Validate language exists in constants
$available_languages = array_keys(config('constants.langs'));
if (!in_array($language, $available_languages)) {
return response()->json(['success' => false, 'message' => 'Invalid language selected'], 400);
}
// Update user language
$user->language = $language;
$user->save();
// Update session locale for UI translations
app()->setLocale($language);
session(['locale' => $language, 'user.language' => $language]);
// Keep Carbon in English for consistent date operations
\Carbon\Carbon::setLocale('en');
return response()->json(['success' => true, 'message' => 'Language updated successfully']);
} catch (\Exception $e) {
\Log::emergency('File:'.$e->getFile().'Line:'.$e->getLine().'Message:'.$e->getMessage());
return response()->json(['success' => false, 'message' => 'Failed to update language'], 500);
}
}
Step 6: Add Routeβ
Add a route for the language update endpoint.
File: routes/web.php
β
Route::post('/users/update-language', [ManageUserController::class, 'updateLanguage'])->name('users.update-language');
Step 7: Update Login Controllerβ
Ensure the user's language is set when they log in.
File: app/Http/Controllers/Auth/LoginController.php
β
Add this to the authenticated
method:
protected function authenticated(Request $request, $user)
{
// ... existing code ...
// Set user's language preference
if (!empty($user->language)) {
$availableLanguages = array_keys(config('constants.langs', []));
if (in_array($user->language, $availableLanguages)) {
// Set locale for UI translations
app()->setLocale($user->language);
session(['locale' => $user->language, 'user.language' => $user->language]);
// Keep Carbon in English for date operations
\Carbon\Carbon::setLocale('en');
}
}
// ... rest of existing code ...
}
Step 8: Create Language Dropdownβ
Add the language dropdown to your header.
File: resources/views/layouts/partials/header.blade.php
β
{{-- Language Dropdown --}}
<details class="tw-dw-dropdown tw-relative tw-inline-block tw-text-left">
<summary
class="tw-inline-flex tw-transition-all tw-ring-1 tw-ring-white/10 hover:tw-text-white tw-cursor-pointer tw-duration-200 tw-bg-primary-800 hover:tw-bg-primary-700 tw-py-1.5 tw-px-3 tw-rounded-lg tw-items-center tw-justify-center tw-text-sm tw-font-medium tw-text-white tw-gap-2">
<span class="fi fi-{{ config('constants.langs')[Auth::user()->language]['flag_code'] ?? 'us' }} tw-text-sm"></span>
<span class="tw-hidden md:tw-block">{{ config('constants.langs')[Auth::user()->language]['short_name'] ?? 'English' }}</span>
</summary>
<ul class="tw-p-2 tw-w-56 tw-absolute tw-right-0 tw-z-10 tw-mt-2 tw-origin-top-right tw-bg-white tw-rounded-lg tw-shadow-lg tw-ring-1 tw-ring-gray-200 focus:tw-outline-none"
role="menu" tabindex="-1">
@foreach (config('constants.langs') as $key => $val)
<li>
<a href="javascript:void(0)"
class="change_user_language tw-flex tw-items-center tw-gap-3 tw-px-3 tw-py-2 tw-text-sm tw-font-medium tw-text-gray-600 tw-transition-all tw-duration-200 tw-rounded-lg hover:tw-text-gray-900 hover:tw-bg-gray-100 @if(Auth::user()->language == $key) tw-bg-gray-100 tw-text-gray-900 @endif"
data-language="{{ $key }}"
role="menuitem" tabindex="-1">
<span class="fi fi-{{ $val['flag_code'] ?? 'un' }} tw-text-sm"></span>
<span class="tw-flex-1">{{ $val['full_name'] }}</span>
@if(Auth::user()->language == $key)
<svg class="tw-w-4 tw-h-4" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path>
</svg>
@endif
</a>
</li>
@endforeach
</ul>
</details>
Step 9: Add JavaScript Handlerβ
Add JavaScript to handle the language change functionality.
File: resources/views/layouts/partials/javascripts.blade.php
β
<script>
$(document).ready(function() {
// Handle language change
$(document).on('click', '.change_user_language', function(e) {
e.preventDefault();
var language = $(this).data('language');
$.ajax({
url: '{{ route("users.update-language") }}',
type: 'POST',
data: {
language: language,
_token: '{{ csrf_token() }}'
},
success: function(response) {
if (response.success) {
// Reload the page to apply the new language
window.location.reload();
} else {
toastr.error(response.message || 'Failed to update language');
}
},
error: function(xhr, status, error) {
toastr.error('Failed to update language');
}
});
});
});
</script>
Step 10: Clear Cachesβ
Clear your application caches to ensure all changes take effect:
php artisan config:cache
php artisan view:clear
php artisan route:clear
Testingβ
- Login to your application
- Click the language dropdown in the header
- Select a different language
- Verify the page reloads in the new language
- Check that the language preference persists after logout/login
Customizationβ
Adding New Languagesβ
- Add language files to
lang/
directory - Add JavaScript language files to
public/js/lang/
- Update
config/constants.php
with new language entry - Include appropriate flag code
Stylingβ
Modify the CSS classes in the header template to match your application's design system.
Flag Sourcesβ
The implementation uses the Flag Icons CSS library. You can also use:
- Local flag images
- Different flag icon libraries
- Custom SVG flags
Troubleshootingβ
Language Not Changingβ
- Check middleware is registered correctly
- Verify language files exist
- Ensure session is working properly
Flags Not Displayingβ
- Verify Flag Icons CSS is loaded
- Check flag codes match the library format
- Ensure internet connection for CDN
Database Errorsβ
- Verify users table has language column
- Check column type allows sufficient length
- Ensure database permissions are correct
Conclusionβ
You now have a fully functional user-specific language dropdown with country flags that:
- Allows each user to set their preferred language
- Saves preferences to the database
- Automatically applies language across the application
- Uses beautiful country flag icons
- Provides a professional, responsive interface
The implementation is scalable and can easily accommodate additional languages as your application grows.
π Support this project