Last summer, I inherited a Laravel API for a Saudi real estate portal. The client kept getting complaints that Arabic property descriptions looked like a garbled mess in the mobile app. I clicked through their staging environment — sure enough, الْعَرَبِيّة turned into ‫العربية‬. Not exactly the vibe when you're selling villas in Riyadh.
The Database Layer: UTF8 Is a Lie
If you’re using Laravel’s default MySQL configuration, stop right now. The utf8 charset MySQL ships with? It doesn’t actually handle Arabic properly. You need utf8mb4. Took me three projects to learn this. Don’t be me.
In config/database.php, change your charset and collation settings like so:
'mysql' => [
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
]But wait — your database tables won’t update themselves. I had to run raw queries to fix existing data:
ALTER TABLE properties CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Miss this step, and older records will still look broken. Laravel won’t yell at you. The world will just quietly hate you.
PHP Configuration: Blame Your Own Machine
Turns out even perfect Laravel settings can get wrecked by PHP’s mbstring defaults. Found this out after spending 4 hours swearing at my test cases.
Check your php.ini:
mbstring.language = Arabic
mbstring.internal_encoding = UTF-8
mbstring.http_input = UTF-8
mbstring.http_output = UTF-8
mbstring.encoding_translation = 1If you’re using Laravel Sail or Docker containers, make sure these changes are in both host and container environments. I once chased this bug because docker-compose up was reading an outdated image. Never again.
When It Still Broke For No Reason
The worst part? Even after DB and PHP side worked, my response headers were fighting me. Laravel by default sends Content-Type: text/html for APIs. Which meant some browsers were guessing encodings like it was 2003.
Fixed it by forcing a charset in the response:
$response = response()->json($data);
$response->headers->set('Content-Type', 'application/json; charset=UTF-8');
return $response;Wish there was a centralized way to handle this. Maybe a middleware someday when I’m less lazy.
Real Testing Means Using Arabic Input
You can’t just test with Postman. I used a form from a UAE event management client that sends Arabic names through Tawasul Limo’s booking system. Real POST payloads from actual Android phones revealed issues with normalisation — like how ة gets transformed during validation.
Pro tip: Use \Illuminate\Support\Str::ascii() with extreme caution. It mangles Arabic text by design. We ended up whitelisting Arabic ranges in our input sanitation rules.
Validator::make($request->all(), [
'name' => ['required', 'regex:/^[\p{Arabic}\p{L}\p{N} ]+$/u']
]);The Human Part
I once spent two days debugging a client’s SMS gateway integration for Reach Home Properties, because the provider had hardcoded cp1256 support. Laravel was doing everything right. Their API was just… bad. Had to force iconv('UTF-8', 'WINDOWS-1256//TRANSLIT//IGNORE', $text) for their endpoint. Still makes my skin crawl.
Wrap Up
If your Laravel API serves Arabic audiences — which it should, given the GCC’s growing app market — these aren’t optional steps. Some clients expect perfect Arabic handling out of the box. They’re not wrong.
Got questions? Found a better way to handle this? Hit me up on sarahprofile.com/contact. I’ll probably steal your idea for the next client in Jeddah.