migrant-web/app/Http/Controllers/Api/WorkerAuthController.php
2026-06-09 09:51:59 +05:30

789 lines
62 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Worker;
use App\Models\WorkerCategory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class WorkerAuthController extends Controller
{
/**
* Get system configuration and supported languages for worker onboarding.
* Aligns with Step 2 "Select Language (HI / SW / TL / TA)".
*/
public function config()
{
return response()->json([
'success' => true,
'languages' => [
['code' => 'HI', 'name' => 'Hindi (हिन्दी)'],
['code' => 'SW', 'name' => 'Swahili (Kiswahili)'],
['code' => 'TL', 'name' => 'Tagalog (Wikang Tagalog)'],
['code' => 'TA', 'name' => 'Tamil (தமிழ்)'],
]
], 200);
}
/**
* Get all master skills for worker registration/onboarding.
*/
public function skills()
{
$skills = \App\Models\Skill::all()->map(function ($skill) {
return [
'id' => $skill->id,
'name' => $skill->name,
];
});
return response()->json([
'success' => true,
'skills' => $skills
], 200);
}
/**
* Step 1: Send OTP to worker's mobile number or email.
* Accepts: phone OR email (one is required).
*/
public function sendOtp(Request $request)
{
$validator = Validator::make($request->all(), [
'phone' => 'required_without:email|nullable|string|max:50',
'email' => 'required_without:phone|nullable|email|max:255',
], [
'phone.required_without' => 'Please provide a mobile number or email address.',
'email.required_without' => 'Please provide a mobile number or email address.',
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => 'Validation error.',
'errors' => $validator->errors()
], 422);
}
// Determine identifier (phone takes priority)
$identifier = $request->phone ?? $request->email;
$isPhone = !empty($request->phone);
// Generate OTP (always 111111 in local/dev, random in production)
$otp = app()->environment('production') ? strval(rand(100000, 999999)) : '111111';
// Cache OTP for 10 minutes
Cache::put('worker_otp_' . $identifier, [
'code' => $otp,
'expires_at' => now()->addMinutes(10)->timestamp,
], 600);
// Send OTP via email if email provided (phone SMS would be handled by SMS gateway)
if (!$isPhone && $request->email) {
try {
Mail::raw("Your Migrant Worker verification code is: {$otp}\n\nThis code expires in 10 minutes.", function ($m) use ($request, $otp) {
$m->to($request->email)
->subject('Your Migrant Worker Verification Code');
});
} catch (\Exception $mailEx) {
logger()->error('Worker OTP Mail Failure: ' . $mailEx->getMessage());
}
}
return response()->json([
'success' => true,
'message' => $isPhone
? 'OTP sent to your mobile number.'
: 'OTP sent to your email address.',
'identifier' => $identifier,
'otp' => app()->environment('production') ? null : $otp, // Return OTP in response in non-prod for testing convenience
], 200);
}
/**
* Step 2: Verify OTP sent to mobile/email.
* Accepts: phone OR email, otp.
*/
public function verifyOtp(Request $request)
{
$validator = Validator::make($request->all(), [
'phone' => 'required_without:email|nullable|string|max:50',
'email' => 'required_without:phone|nullable|email|max:255',
'otp' => 'required|string|size:6',
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'errors' => $validator->errors()
], 422);
}
$identifier = $request->phone ?? $request->email;
$cachedData = Cache::get('worker_otp_' . $identifier);
if (!$cachedData || !isset($cachedData['code']) || !isset($cachedData['expires_at'])) {
return response()->json([
'success' => false,
'message' => 'Invalid or expired verification code.'
], 400);
}
// Handle any dirty/legacy cache objects gracefully
if (is_object($cachedData['expires_at']) || $cachedData['expires_at'] instanceof \__PHP_Incomplete_Class) {
Cache::forget('worker_otp_' . $identifier);
return response()->json([
'success' => false,
'message' => 'Session expired. Please request a new verification code.'
], 400);
}
if ($cachedData['code'] !== $request->otp || now()->timestamp > $cachedData['expires_at']) {
return response()->json([
'success' => false,
'message' => 'Invalid or expired verification code.'
], 400);
}
// Mark OTP as verified in cache (used as gate for profile setup step)
Cache::put('worker_otp_verified_' . $identifier, true, 3600); // 1 hour grace
Cache::forget('worker_otp_' . $identifier);
return response()->json([
'success' => true,
'message' => 'Mobile number verified successfully. Please complete your profile.',
'identifier' => $identifier,
], 200);
}
/**
* Step 3: Complete basic profile setup after OTP verification.
* Accepts: phone OR email, name, nationality, skills (array of skill IDs), language.
*/
public function setupProfile(Request $request)
{
$validator = Validator::make($request->all(), [
'phone' => 'required_without:email|nullable|string|max:50',
'email' => 'required_without:phone|nullable|email|max:255',
'name' => 'required|string|max:255',
'nationality' => 'required|string|max:100',
'language' => 'nullable|string',
'gender' => 'nullable|string|in:male,female,other',
'live_in_out' => 'nullable|string|in:live_in,live_out',
'preferred_location' => 'nullable|string|max:255',
'skills' => 'nullable|array',
'skills.*' => 'integer|exists:skills,id',
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'errors' => $validator->errors()
], 422);
}
$identifier = $request->phone ?? $request->email;
// Ensure OTP was verified in this session
if (!Cache::get('worker_otp_verified_' . $identifier)) {
return response()->json([
'success' => false,
'message' => 'OTP verification is required before profile setup.'
], 403);
}
// Check if already registered
if ($request->phone && Worker::where('phone', $request->phone)->exists()) {
return response()->json([
'success' => false,
'message' => 'This mobile number is already registered.'
], 409);
}
if ($request->email && Worker::where('email', $request->email)->exists()) {
return response()->json([
'success' => false,
'message' => 'This email address is already registered.'
], 409);
}
try {
// Build email for workers who registered by phone
$email = $request->email;
if (!$email && $request->phone) {
$phoneClean = preg_replace('/[^0-9]/', '', $request->phone);
$email = "worker.{$phoneClean}@migrant.ae";
if (Worker::where('email', $email)->exists()) {
$email = "worker.{$phoneClean}." . rand(10, 99) . "@migrant.ae";
}
}
$apiToken = Str::random(80);
$worker = DB::transaction(function () use ($request, $email, $apiToken) {
$worker = Worker::create([
'name' => $request->name,
'email' => $email,
'phone' => $request->phone ?? null,
'language' => $request->language ?? 'HI', // Default to Hindi if not selected
'password' => Hash::make(Str::random(16)), // No password at this stage
'nationality' => $request->nationality,
'gender' => $request->gender,
'live_in_out' => $request->live_in_out,
'preferred_location' => $request->preferred_location,
'age' => 25, // Default — updated later in full profile
'salary' => 1500, // Default AED — updated later
'availability' => 'Immediate',
'experience' => 'Not Specified',
'religion' => 'Not Specified',
'bio' => 'New worker on Migrant platform.',
'category_id' => \App\Models\WorkerCategory::where('name', 'General Helper')->value('id') ?? (\App\Models\WorkerCategory::firstOrCreate(['name' => 'General Helper'])->id),
'verified' => false,
'status' => 'active',
'api_token' => $apiToken,
]);
// Sync skills if provided
if (!empty($request->skills)) {
$worker->skills()->sync($request->skills);
}
return $worker;
});
// Clear the OTP verification gate
Cache::forget('worker_otp_verified_' . $identifier);
$worker->load(['category', 'skills']);
return response()->json([
'success' => true,
'message' => 'Registration complete! Welcome to Migrant.',
'data' => [
'worker' => $worker,
'token' => $apiToken,
]
], 201);
} catch (\Exception $e) {
logger()->error('Worker Profile Setup Failure: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'Registration failed. Please try again.',
'error' => app()->environment('local', 'testing') ? $e->getMessage() : 'Internal Server Error'
], 500);
}
}
/**
* Unified registration — supports backward compatibility and multipart file registration.
*/
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'phone' => 'required|string|max:50|unique:workers,phone',
'salary' => 'required|numeric|min:0',
'password' => 'required|string|min:6',
'passport_file' => 'required|file|mimes:jpeg,png,jpg,pdf|max:10240',
'skills' => 'nullable',
'visa_file' => 'nullable|file|mimes:jpeg,png,jpg,pdf|max:10240',
'language' => 'nullable|string',
'nationality' => 'nullable|string|max:100',
'age' => 'nullable|integer',
'experience' => 'nullable|string|max:100',
'in_country' => 'nullable',
'visa_status' => 'nullable|string|max:100',
'preferred_job_type' => 'nullable|string|max:100',
'gender' => 'nullable|string|in:male,female,other',
'live_in_out' => 'nullable|string|in:live_in,live_out',
'preferred_location' => 'nullable|string|max:255',
'country' => 'nullable|string|max:100',
'city' => 'nullable|string|max:100',
'area' => 'nullable|string|max:100',
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => 'Validation error.',
'errors' => $validator->errors()
], 422);
}
try {
$phoneClean = preg_replace('/[^0-9]/', '', $request->phone);
$email = "worker.{$phoneClean}@migrant.ae";
if (Worker::where('email', $email)->exists()) {
$email = "worker.{$phoneClean}." . rand(10, 99) . "@migrant.ae";
}
$skillsArray = [];
if ($request->has('skills')) {
$skillsInput = $request->skills;
if (is_array($skillsInput)) {
$skillsArray = $skillsInput;
} elseif (is_string($skillsInput)) {
$decoded = json_decode($skillsInput, true);
$skillsArray = (json_last_error() === JSON_ERROR_NONE && is_array($decoded))
? $decoded
: array_filter(array_map('trim', explode(',', $skillsInput)));
}
}
$destinationPath = public_path('uploads/documents');
if (!file_exists($destinationPath)) {
mkdir($destinationPath, 0755, true);
}
$passportPath = null;
$visaPath = null;
if ($request->hasFile('passport_file')) {
$file = $request->file('passport_file');
$fileName = time() . '_passport_' . preg_replace('/[^a-zA-Z0-9_.-]/', '', $file->getClientOriginalName());
$file->move($destinationPath, $fileName);
$passportPath = 'uploads/documents/' . $fileName;
}
if ($request->hasFile('visa_file')) {
$file = $request->file('visa_file');
$fileName = time() . '_visa_' . preg_replace('/[^a-zA-Z0-9_.-]/', '', $file->getClientOriginalName());
$file->move($destinationPath, $fileName);
$visaPath = 'uploads/documents/' . $fileName;
}
$inCountry = filter_var($request->input('in_country', true), FILTER_VALIDATE_BOOLEAN);
$apiToken = Str::random(80);
$result = DB::transaction(function () use ($request, $email, $skillsArray, $passportPath, $visaPath, $apiToken, $inCountry) {
$worker = Worker::create([
'name' => $request->name,
'email' => $email,
'phone' => $request->phone,
'language' => $request->language ?? 'HI',
'password' => Hash::make($request->password),
'nationality' => $request->nationality ?? 'Not Specified',
'gender' => $request->gender,
'live_in_out' => $request->live_in_out,
'preferred_location' => $request->preferred_location,
'age' => $request->age ?? 25,
'salary' => $request->salary,
'availability' => 'Immediate',
'experience' => $request->experience ?? 'Not Specified',
'religion' => 'Not Specified',
'bio' => 'Hardworking and reliable General Helper available for immediate hire.',
'category_id' => \App\Models\WorkerCategory::where('name', 'General Helper')->value('id') ?? (\App\Models\WorkerCategory::firstOrCreate(['name' => 'General Helper'])->id),
'verified' => false,
'status' => 'active',
'api_token' => $apiToken,
'in_country' => $inCountry,
'visa_status' => $inCountry ? $request->visa_status : null,
'preferred_job_type' => $request->preferred_job_type,
'country' => $request->country,
'city' => $request->city,
'area' => $request->area,
]);
if (!empty($skillsArray)) {
$validSkillIds = DB::table('skills')->whereIn('id', $skillsArray)->pluck('id')->toArray();
if (!empty($validSkillIds)) {
$worker->skills()->sync($validSkillIds);
}
}
$worker->documents()->create([
'type' => 'passport',
'number' => 'P' . rand(100000, 999999),
'issue_date' => now()->subYears(2)->toDateString(),
'expiry_date' => now()->addYears(8)->toDateString(),
'ocr_accuracy'=> 98.5,
'file_path' => $passportPath,
]);
$worker->documents()->create([
'type' => 'visa',
'number' => 'V' . rand(100000, 999999),
'issue_date' => now()->subYear()->toDateString(),
'expiry_date' => now()->addYears(2)->toDateString(),
'ocr_accuracy'=> $visaPath ? 98.5 : 0.0,
'file_path' => $visaPath,
]);
return $worker;
});
$result->load(['category', 'skills', 'documents']);
return response()->json([
'success' => true,
'message' => 'Worker registered and authenticated successfully.',
'data' => ['worker' => $result, 'token' => $apiToken]
], 201);
} catch (\Exception $e) {
logger()->error('Worker Registration Failure: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'An error occurred during worker registration. Please try again.',
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
], 500);
}
}
/**
* Authenticate a worker and return a secure Bearer token.
*/
public function login(Request $request)
{
$validator = Validator::make($request->all(), [
'phone' => 'required_without:email|nullable|string',
'email' => 'required_without:phone|nullable|email',
'password' => 'required|string',
]);
if ($validator->fails()) {
return response()->json([
'success' => false,
'message' => 'Validation error.',
'errors' => $validator->errors()
], 422);
}
try {
$worker = $request->phone
? Worker::where('phone', $request->phone)->first()
: Worker::where('email', $request->email)->first();
if (!$worker || !Hash::check($request->password, $worker->password)) {
return response()->json([
'success' => false,
'message' => 'Invalid credentials.'
], 401);
}
$apiToken = Str::random(80);
$worker->update(['api_token' => $apiToken]);
return response()->json([
'success' => true,
'message' => 'Worker logged in successfully.',
'data' => [
'worker' => $worker->load(['category', 'skills', 'documents']),
'token' => $apiToken
]
], 200);
} catch (\Exception $e) {
logger()->error('Worker Login Failure: ' . $e->getMessage());
return response()->json([
'success' => false,
'message' => 'An error occurred during login. Please try again.',
'error' => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
], 500);
}
}
/**
* Get list of nationalities translated to requested language.
* Supports en, hindi (hi), sawahi (sw), taglo (tl), tamil (ta).
*/
public function nationalities(Request $request)
{
$lang = strtolower($request->input('lang') ?? $request->header('Accept-Language') ?? 'en');
if (str_contains($lang, ',')) {
$lang = explode(',', $lang)[0];
}
if (str_contains($lang, '-')) {
$lang = explode('-', $lang)[0];
}
$langMap = [
'hindi' => 'hi',
'sawahi' => 'sw',
'swahili' => 'sw',
'taglo' => 'tl',
'tagalog' => 'tl',
'tamil' => 'ta',
];
if (isset($langMap[$lang])) {
$lang = $langMap[$lang];
}
if (!in_array($lang, ['en', 'hi', 'sw', 'tl', 'ta'])) {
$lang = 'en';
}
$rawNationalities = [
['code' => 'AF', 'name' => 'Afghan', 'hi' => 'अफ़ग़ान', 'sw' => 'Waafgani', 'tl' => 'Afghan', 'ta' => 'ஆப்கானியர்'],
['code' => 'AL', 'name' => 'Albanian', 'hi' => 'अल्बानियाई', 'sw' => 'Mwalbania', 'tl' => 'Albanian', 'ta' => 'அல்பேனியன்'],
['code' => 'DZ', 'name' => 'Algerian', 'hi' => 'अल्जीरियाई', 'sw' => 'Mwaljeria', 'tl' => 'Algerian', 'ta' => 'அல்ஜீரியன்'],
['code' => 'US', 'name' => 'American', 'hi' => 'अमेरिकी', 'sw' => 'Mmarekani', 'tl' => 'Amerikano', 'ta' => 'அமெரிக்கன்'],
['code' => 'AD', 'name' => 'Andorran', 'hi' => 'अंडोरन', 'sw' => 'Mandora', 'tl' => 'Andorran', 'ta' => 'அண்டோரன்'],
['code' => 'AO', 'name' => 'Angolan', 'hi' => 'अंगोलन', 'sw' => 'Mwangola', 'tl' => 'Angolan', 'ta' => 'अंगोलन'],
['code' => 'AI', 'name' => 'Anguillan', 'hi' => 'अंगुइला का', 'sw' => 'Manguilla', 'tl' => 'Anguillan', 'ta' => 'அங்குயிலன்'],
['code' => 'AG', 'name' => 'Citizen of Antigua and Barbuda', 'hi' => 'एंटीगुआ और बारबुडा का नागरिक', 'sw' => 'Mwananchi wa Antigua na Barbuda', 'tl' => 'Citizen of Antigua and Barbuda', 'ta' => 'ஆன்டிகுவா மற்றும் பார்புடா குடிமகன்'],
['code' => 'AR', 'name' => 'Argentine', 'hi' => 'अर्जेंटीना का', 'sw' => 'Mwargentina', 'tl' => 'Argentine', 'ta' => 'அர்ஜென்டினியர்'],
['code' => 'AM', 'name' => 'Armenian', 'hi' => 'अर्मेनियाई', 'sw' => 'Mwarmenia', 'tl' => 'Armenian', 'ta' => 'அர்மீனியன்'],
['code' => 'AU', 'name' => 'Australian', 'hi' => 'ऑस्ट्रेलियाई', 'sw' => 'Mwaustralia', 'tl' => 'Australian', 'ta' => 'ஆஸ்திரேலியர்'],
['code' => 'AT', 'name' => 'Austrian', 'hi' => 'ऑस्ट्रियाई', 'sw' => 'Mwaustria', 'tl' => 'Austrian', 'ta' => 'ஆஸ்திரியன்'],
['code' => 'AZ', 'name' => 'Azerbaijani', 'hi' => 'अज़रबैजानी', 'sw' => 'Mwazeria', 'tl' => 'Azerbaijani', 'ta' => 'அஜர்பைஜானி'],
['code' => 'BS', 'name' => 'Bahamian', 'hi' => 'बहामियन', 'sw' => 'Mbahama', 'tl' => 'Bahamian', 'ta' => 'பஹாமியன்'],
['code' => 'BH', 'name' => 'Bahraini', 'hi' => 'बहरीनी', 'sw' => 'Mbahraini', 'tl' => 'Bahraini', 'ta' => 'பஹ்ரைனி'],
['code' => 'BD', 'name' => 'Bangladeshi', 'hi' => 'बांग्लादेशी', 'sw' => 'Mbangladeshi', 'tl' => 'Bangladeshi', 'ta' => 'பங்களாதேஷ்'],
['code' => 'BB', 'name' => 'Barbadian', 'hi' => 'बारबेडियन', 'sw' => 'Mbarbados', 'tl' => 'Barbadian', 'ta' => 'பார்பேடியன்'],
['code' => 'BY', 'name' => 'Belarusian', 'hi' => 'बेलारूसी', 'sw' => 'Mbelarusi', 'tl' => 'Belarusian', 'ta' => 'பெலாரஷ்யன்'],
['code' => 'BE', 'name' => 'Belgian', 'hi' => 'बेल्जियम का', 'sw' => 'Mbelgiji', 'tl' => 'Belgian', 'ta' => 'பெல்ஜியன்'],
['code' => 'BZ', 'name' => 'Belizean', 'hi' => 'बेलीज़ का', 'sw' => 'Mbelize', 'tl' => 'Belizean', 'ta' => 'பெலிஸியன்'],
['code' => 'BJ', 'name' => 'Beninese', 'hi' => 'बेनीनी', 'sw' => 'Mbenini', 'tl' => 'Beninese', 'ta' => 'பெனினீஸ்'],
['code' => 'BM', 'name' => 'Bermudian', 'hi' => 'बरमूडा का', 'sw' => 'Mbermuda', 'tl' => 'Bermudian', 'ta' => 'பெர்முடியன்'],
['code' => 'BT', 'name' => 'Bhutanese', 'hi' => 'भूटानी', 'sw' => 'Mbhutani', 'tl' => 'Bhutanese', 'ta' => 'பூட்டானியர்'],
['code' => 'BO', 'name' => 'Bolivian', 'hi' => 'बोलिवियाई', 'sw' => 'Mbolivia', 'tl' => 'Bolivian', 'ta' => 'பொலிவியன்'],
['code' => 'BA', 'name' => 'Citizen of Bosnia and Herzegovina', 'hi' => 'बोस्निया और हर्जेगोविना का नागरिक', 'sw' => 'Mwananchi wa Bosnia na Herzegovina', 'tl' => 'Citizen of Bosnia and Herzegovina', 'ta' => 'போஸ்னியா மற்றும் ஹெர்சகோவினா குடிமகன்'],
['code' => 'BW', 'name' => 'Botswanan', 'hi' => 'बोत्सवाना का', 'sw' => 'Mswana', 'tl' => 'Botswanan', 'ta' => 'போட்ஸ்வானா'],
['code' => 'BR', 'name' => 'Brazilian', 'hi' => 'ब्राज़ीलियाई', 'sw' => 'Mbrazili', 'tl' => 'Brazilian', 'ta' => 'பிரேசிலியன்'],
['code' => 'GB', 'name' => 'British', 'hi' => 'ब्रिटिश', 'sw' => 'Mwingereza', 'tl' => 'British', 'ta' => 'பிரிட்டிஷ்'],
['code' => 'VG', 'name' => 'British Virgin Islander', 'hi' => 'ब्रिटिश वर्जिन द्वीप समूह का नागरिक', 'sw' => 'Mkaazi wa Visiwa vya Virgin vya Uingereza', 'tl' => 'British Virgin Islander', 'ta' => 'பிரிட்டிஷ் விர்ஜின் தீவுவாசி'],
['code' => 'BN', 'name' => 'Bruneian', 'hi' => 'ब्रुनेई का', 'sw' => 'Mbrunei', 'tl' => 'Bruneian', 'ta' => 'புருனேயன்'],
['code' => 'BG', 'name' => 'Bulgarian', 'hi' => 'बुल्गारियाई', 'sw' => 'Mbulgaria', 'tl' => 'Bulgarian', 'ta' => 'பல்கேரியன்'],
['code' => 'BF', 'name' => 'Burkinan', 'hi' => 'बुर्किना का', 'sw' => 'Mburkina', 'tl' => 'Burkinan', 'ta' => 'புர்கினன்'],
['code' => 'MM', 'name' => 'Burmese', 'hi' => 'बर्मी', 'sw' => 'Mburma', 'tl' => 'Burmese', 'ta' => 'பர்மீஸ்'],
['code' => 'BI', 'name' => 'Burundian', 'hi' => 'बुरुंडी का', 'sw' => 'Mrundi', 'tl' => 'Burundian', 'ta' => 'புருண்டியன்'],
['code' => 'KH', 'name' => 'Cambodian', 'hi' => 'कंबोडियाई', 'sw' => 'Mkambodia', 'tl' => 'Cambodian', 'ta' => 'கம்போடியன்'],
['code' => 'CM', 'name' => 'Cameroonian', 'hi' => 'कैमरून का', 'sw' => 'Mkameruni', 'tl' => 'Cameroonian', 'ta' => 'கேமரூனியன்'],
['code' => 'CA', 'name' => 'Canadian', 'hi' => 'कनाडाई', 'sw' => 'Mkanada', 'tl' => 'Canadian', 'ta' => 'கனடியன்'],
['code' => 'CV', 'name' => 'Cape Verdean', 'hi' => 'केप वर्ड का', 'sw' => 'Mkaboverde', 'tl' => 'Cape Verdean', 'ta' => 'கேப் வெர்டியன்'],
['code' => 'KY', 'name' => 'Cayman Islander', 'hi' => 'केमैन द्वीप समूह का नागरिक', 'sw' => 'Mkaazi wa Visiwa vya Cayman', 'tl' => 'Cayman Islander', 'ta' => 'கேமன் தீவுவாசி'],
['code' => 'CF', 'name' => 'Central African', 'hi' => 'मध्य अफ्रीकी', 'sw' => 'Mkaazi wa Afrika ya Kati', 'tl' => 'Central African', 'ta' => 'மத்திய ஆப்பிரிக்கர்'],
['code' => 'TD', 'name' => 'Chadian', 'hi' => 'चाड का', 'sw' => 'Mchadi', 'tl' => 'Chadian', 'ta' => 'சாடியன்'],
['code' => 'CL', 'name' => 'Chilean', 'hi' => 'चिली का', 'sw' => 'Mchile', 'tl' => 'Chilean', 'ta' => 'சிலியன்'],
['code' => 'CN', 'name' => 'Chinese', 'hi' => 'चीनी', 'sw' => 'Mchina', 'tl' => 'Intsik', 'ta' => 'சீனர்'],
['code' => 'CO', 'name' => 'Colombian', 'hi' => 'कोलंबियाई', 'sw' => 'Mkolombia', 'tl' => 'Colombian', 'ta' => 'கொலம்பியன்'],
['code' => 'KM', 'name' => 'Comoran', 'hi' => 'कोमोरियन', 'sw' => 'Mkomoro', 'tl' => 'Comoran', 'ta' => 'கொமோரியன்'],
['code' => 'CG', 'name' => 'Congolese (Congo)', 'hi' => 'कांगो का', 'sw' => 'Mkongo', 'tl' => 'Congolese', 'ta' => 'காங்கோலிஸ் (காங்கோ)'],
['code' => 'CD', 'name' => 'Congolese (DRC)', 'hi' => 'डीआर कांगो का', 'sw' => 'Mkongo wa DRC', 'tl' => 'Congolese', 'ta' => 'காங்கோலிஸ் (டிஆர்सी)'],
['code' => 'CK', 'name' => 'Cook Islander', 'hi' => 'कुक द्वीप समूह का', 'sw' => 'Mkaazi wa Visiwa vya Cook', 'tl' => 'Cook Islander', 'ta' => 'குக் தீவுவாசி'],
['code' => 'CR', 'name' => 'Costa Rican', 'hi' => 'कोस्टा रिका का', 'sw' => 'Mkostarika', 'tl' => 'Costa Rican', 'ta' => 'கோஸ்டா ரிகான்'],
['code' => 'HR', 'name' => 'Croatian', 'hi' => 'क्रोएशियाई', 'sw' => 'Mkroatia', 'tl' => 'Croatian', 'ta' => 'குரோஷியன்'],
['code' => 'CU', 'name' => 'Cuban', 'hi' => 'क्यूबा का', 'sw' => 'Mkyuba', 'tl' => 'Cuban', 'ta' => 'कியூபன்'],
['code' => 'CY-W', 'name' => 'Cymraes', 'hi' => 'वेल्श महिला', 'sw' => 'Mwelshi wa Kike', 'tl' => 'Cymraes', 'ta' => 'வெல்ஷ் பெண்'],
['code' => 'CY-M', 'name' => 'Cymro', 'hi' => 'वेल्श पुरुष', 'sw' => 'Mwelshi wa Kiume', 'tl' => 'Cymro', 'ta' => 'வெல்ஷ் ஆண்'],
['code' => 'CY', 'name' => 'Cypriot', 'hi' => 'साइप्रस का', 'sw' => 'Msaiprasi', 'tl' => 'Cypriot', 'ta' => 'சைப்ரியாட்'],
['code' => 'CZ', 'name' => 'Czech', 'hi' => 'चेक', 'sw' => 'Mcheki', 'tl' => 'Czech', 'ta' => 'செக்'],
['code' => 'DK', 'name' => 'Danish', 'hi' => 'डेनिश', 'sw' => 'Mdeni', 'tl' => 'Danish', 'ta' => 'டேனிஷ்'],
['code' => 'DJ', 'name' => 'Djiboutian', 'hi' => 'जिबूती का', 'sw' => 'Mdjibuti', 'tl' => 'Djiboutian', 'ta' => 'ஜிபூட்டியன்'],
['code' => 'DM', 'name' => 'Dominican', 'hi' => 'डोमिनिकन', 'sw' => 'Mdominika', 'tl' => 'Dominican', 'ta' => 'டொமினிக்கன்'],
['code' => 'DO', 'name' => 'Citizen of the Dominican Republic', 'hi' => 'डोमिनिकन गणराज्य का नागरिक', 'sw' => 'Mwananchi wa Jamhuri ya Dominika', 'tl' => 'Citizen of the Dominican Republic', 'ta' => 'டொமினிக்கன் குடியரசு குடிமகன்'],
['code' => 'NL', 'name' => 'Dutch', 'hi' => 'डच', 'sw' => 'Mholanzi', 'tl' => 'Dutch', 'ta' => 'டச்சு'],
['code' => 'TL', 'name' => 'East Timorese', 'hi' => 'पूर्वी तिमोर का', 'sw' => 'Mtimor-Mashariki', 'tl' => 'East Timorese', 'ta' => 'கிழக்கு திமோர்'],
['code' => 'EC', 'name' => 'Ecuadorean', 'hi' => 'इक्वाडोर का', 'sw' => 'Mekwado', 'tl' => 'Ecuadorean', 'ta' => 'ஈக்வடோரியன்'],
['code' => 'EG', 'name' => 'Egyptian', 'hi' => 'मिस्र का', 'sw' => 'Mmisri', 'tl' => 'Egyptian', 'ta' => 'எகிப்தியன்'],
['code' => 'AE', 'name' => 'Emirati', 'hi' => 'अमीराती', 'sw' => 'Mwarabu wa UAE', 'tl' => 'Emirati', 'ta' => 'எமிராட்டி'],
['code' => 'EN', 'name' => 'English', 'hi' => 'अंग्रेजी', 'sw' => 'Mwingereza', 'tl' => 'English', 'ta' => 'ஆங்கிலேயர்'],
['code' => 'GQ', 'name' => 'Equatorial Guinean', 'hi' => 'भूमध्यरेखीय गिनी का', 'sw' => 'Mginikweta', 'tl' => 'Equatorial Guinean', 'ta' => 'எக்குவடோரியல் கினியன்'],
['code' => 'ER', 'name' => 'Eritrean', 'hi' => 'इरिट्रियाई', 'sw' => 'Mueritrea', 'tl' => 'Eritrean', 'ta' => 'எரித்திரியன்'],
['code' => 'EE', 'name' => 'Estonian', 'hi' => 'एस्टोनियाई', 'sw' => 'Mestonia', 'tl' => 'Estonian', 'ta' => 'எஸ்டோனியன்'],
['code' => 'ET', 'name' => 'Ethiopian', 'hi' => 'इथियोपियाई', 'sw' => 'Mhabeshi', 'tl' => 'Ethiopian', 'ta' => 'எத்தியோப்பியன்'],
['code' => 'FO', 'name' => 'Faroese', 'hi' => 'फेरो द्वीप समूह का', 'sw' => 'Mfaro', 'tl' => 'Faroese', 'ta' => 'பரோயீஸ்'],
['code' => 'FJ', 'name' => 'Fijian', 'hi' => 'फिजी का', 'sw' => 'Mfiji', 'tl' => 'Fijian', 'ta' => 'பிஜியன்'],
['code' => 'PH', 'name' => 'Filipino', 'hi' => 'फ़िलिपिनो', 'sw' => 'Wafilipino', 'tl' => 'Pilipino', 'ta' => 'பிலிப்பைன்ஸ்'],
['code' => 'FI', 'name' => 'Finnish', 'hi' => 'फिनिश', 'sw' => 'Mfini', 'tl' => 'Finnish', 'ta' => 'பின்னிஷ்'],
['code' => 'FR', 'name' => 'French', 'hi' => 'फ्रांसीसी', 'sw' => 'Mfaransa', 'tl' => 'Pranses', 'ta' => 'பிரெஞ்சு'],
['code' => 'GA', 'name' => 'Gabonese', 'hi' => 'गैबॉन का', 'sw' => 'Mgaboni', 'tl' => 'Gabonese', 'ta' => 'கேபோனீஸ்'],
['code' => 'GM', 'name' => 'Gambian', 'hi' => 'गाम्बिया का', 'sw' => 'Mgambia', 'tl' => 'Gambian', 'ta' => 'காம்பியன்'],
['code' => 'GE', 'name' => 'Georgian', 'hi' => 'जॉर्जियाई', 'sw' => 'Mjojia', 'tl' => 'Georgian', 'ta' => 'ஜார்ஜியன்'],
['code' => 'DE', 'name' => 'German', 'hi' => 'जर्मन', 'sw' => 'Mjerumani', 'tl' => 'Aleman', 'ta' => 'ஜெர்மன்'],
['code' => 'GH', 'name' => 'Ghanaian', 'hi' => 'घाना का', 'sw' => 'Mghana', 'tl' => 'Ghanaian', 'ta' => 'கானியன்'],
['code' => 'GI', 'name' => 'Gibraltarian', 'hi' => 'जिब्राल्टर का', 'sw' => 'Mgibralta', 'tl' => 'Gibraltarian', 'ta' => 'ஜிப்ரால்டரியன்'],
['code' => 'GR', 'name' => 'Greek', 'hi' => 'यूनानी', 'sw' => 'Mgiriki', 'tl' => 'Greek', 'ta' => 'கிரேக்கர்'],
['code' => 'GL', 'name' => 'Greenlandic', 'hi' => 'ग्रीनलैंड का', 'sw' => 'Mgreenland', 'tl' => 'Greenlandic', 'ta' => 'கிரீன்லாந்திக்'],
['code' => 'GD', 'name' => 'Grenadian', 'hi' => 'ग्रेनाडा का', 'sw' => 'Mgrenada', 'tl' => 'Grenadian', 'ta' => 'கிரெனடியन'],
['code' => 'GU', 'name' => 'Guamanian', 'hi' => 'गुआम का', 'sw' => 'Mguam', 'tl' => 'Guamanian', 'ta' => 'குவாமேனியன்'],
['code' => 'GT', 'name' => 'Guatemalan', 'hi' => 'ग्वाटेमाला का', 'sw' => 'Mguatemala', 'tl' => 'Guatemalan', 'ta' => 'குவாத்தமாலன்'],
['code' => 'GW', 'name' => 'Citizen of Guinea-Bissau', 'hi' => 'गिनी-बिसाऊ का नागरिक', 'sw' => 'Mwananchi wa Guinea-Bissau', 'tl' => 'Citizen of Guinea-Bissau', 'ta' => 'கினி-பிசாவு குடிமகன்'],
['code' => 'GN', 'name' => 'Guinean', 'hi' => 'गिनी का', 'sw' => 'Mginia', 'tl' => 'Guinean', 'ta' => 'கினியன்'],
['code' => 'GY', 'name' => 'Guyanese', 'hi' => 'गुयाना का', 'sw' => 'Mguyana', 'tl' => 'Guyanese', 'ta' => 'கயானீஸ்'],
['code' => 'HT', 'name' => 'Haitian', 'hi' => 'हैती का', 'sw' => 'Mhaiti', 'tl' => 'Haitian', 'ta' => 'ஹைட்டியன்'],
['code' => 'HN', 'name' => 'Honduran', 'hi' => 'होंडुरास का', 'sw' => 'Mhondurasi', 'tl' => 'Honduran', 'ta' => 'ஹोண்டுரான்'],
['code' => 'HK', 'name' => 'Hong Konger', 'hi' => 'हांगकांग का', 'sw' => 'Mkaazi wa Hong Kong', 'tl' => 'Hong Konger', 'ta' => 'ஹாங்காங்கர்'],
['code' => 'HU', 'name' => 'Hungarian', 'hi' => 'हंगेरियन', 'sw' => 'Mhungaria', 'tl' => 'Hungarian', 'ta' => 'ஹங்கேரியன்'],
['code' => 'IS', 'name' => 'Icelandic', 'hi' => 'आइसलैंड का', 'sw' => 'Miaislandi', 'tl' => 'Icelandic', 'ta' => 'ஐஸ்லாந்திக்'],
['code' => 'IN', 'name' => 'Indian', 'hi' => 'भारतीय', 'sw' => 'Kihindi', 'tl' => 'Kano/Indian', 'ta' => 'இந்தியன்'],
['code' => 'ID', 'name' => 'Indonesian', 'hi' => 'इंडोनेशियाई', 'sw' => 'Mwindonesia', 'tl' => 'Indonesian', 'ta' => 'இந்தோனேசிய'],
['code' => 'IR', 'name' => 'Iranian', 'hi' => 'ईरानी', 'sw' => 'Mwirani', 'tl' => 'Iranian', 'ta' => 'ஈரானியர்'],
['code' => 'IQ', 'name' => 'Iraqi', 'hi' => 'इराकी', 'sw' => 'Mwiraki', 'tl' => 'Iraqi', 'ta' => 'ஈராக்கியர்'],
['code' => 'IE', 'name' => 'Irish', 'hi' => 'आयरिश', 'sw' => 'Miairishi', 'tl' => 'Irish', 'ta' => 'ஐரிஷ்'],
['code' => 'IL', 'name' => 'Israeli', 'hi' => 'इजरायली', 'sw' => 'Mwisraeli', 'tl' => 'Israeli', 'ta' => 'இஸ்ரேலி'],
['code' => 'IT', 'name' => 'Italian', 'hi' => 'इतालवी', 'sw' => 'Mwitaliano', 'tl' => 'Italian', 'ta' => 'இத்தாலியன்'],
['code' => 'CI', 'name' => 'Ivorian', 'hi' => 'आइवेरियन', 'sw' => 'Mkodivaa', 'tl' => 'Ivorian', 'ta' => 'ஐவோரியன்'],
['code' => 'JM', 'name' => 'Jamaican', 'hi' => 'जमैकन', 'sw' => 'Mjamaika', 'tl' => 'Jamaican', 'ta' => 'ஜமைக்கன்'],
['code' => 'JP', 'name' => 'Japanese', 'hi' => 'जापानी', 'sw' => 'Mjapani', 'tl' => 'Hapon', 'ta' => 'ஜப்பானியர்'],
['code' => 'JO', 'name' => 'Jordanian', 'hi' => 'जॉर्डन का', 'sw' => 'Mjordani', 'tl' => 'Jordanian', 'ta' => 'ஜோர்டானியன்'],
['code' => 'KZ', 'name' => 'Kazakh', 'hi' => 'कज़ाख', 'sw' => 'Mkazakhi', 'tl' => 'Kazakh', 'ta' => 'கசாக்'],
['code' => 'KE', 'name' => 'Kenyan', 'hi' => 'केन्याई', 'sw' => 'Mkenya', 'tl' => 'Kenyan', 'ta' => 'கென்யன்'],
['code' => 'KN', 'name' => 'Kittitian', 'hi' => 'किटिटियन', 'sw' => 'Mkittits', 'tl' => 'Kittitian', 'ta' => 'கிட்டிஷியன்'],
['code' => 'KI', 'name' => 'Citizen of Kiribati', 'hi' => 'किरिबाती का नागरिक', 'sw' => 'Mwananchi wa Kiribati', 'tl' => 'Citizen of Kiribati', 'ta' => 'கிரிபதி குடிமகன்'],
['code' => 'XK', 'name' => 'Kosovan', 'hi' => 'कोसोवो का', 'sw' => 'Mkosovo', 'tl' => 'Kosovan', 'ta' => 'கொசோவன்'],
['code' => 'KW', 'name' => 'Kuwaiti', 'hi' => 'कुवैती', 'sw' => 'Mkuwaiti', 'tl' => 'Kuwaiti', 'ta' => 'குவைத்தி'],
['code' => 'KG', 'name' => 'Kyrgyz', 'hi' => 'किर्गिज़', 'sw' => 'Mkirgizi', 'tl' => 'Kyrgyz', 'ta' => 'கிர்கிஸ்'],
['code' => 'LA', 'name' => 'Lao', 'hi' => 'लाओ', 'sw' => 'Mlao', 'tl' => 'Lao', 'ta' => 'லாவோ'],
['code' => 'LV', 'name' => 'Latvian', 'hi' => 'लातवियाई', 'sw' => 'Mlatvia', 'tl' => 'Latvian', 'ta' => 'லாட்வியன்'],
['code' => 'LB', 'name' => 'Lebanese', 'hi' => 'लेबनानी', 'sw' => 'Mlebanoni', 'tl' => 'Lebanese', 'ta' => 'லெபனானியர்'],
['code' => 'LR', 'name' => 'Liberian', 'hi' => 'लाइबेरियाई', 'sw' => 'Mliberia', 'tl' => 'Liberian', 'ta' => 'லைபீரியன்'],
['code' => 'LY', 'name' => 'Libyan', 'hi' => 'लीबिया का', 'sw' => 'Mlibya', 'tl' => 'Libyan', 'ta' => 'லிபியன்'],
['code' => 'LI', 'name' => 'Liechtenstein citizen', 'hi' => 'लिकटेंस्टीन का नागरिक', 'sw' => 'Mwananchi wa Liechtenstein', 'tl' => 'Liechtenstein citizen', 'ta' => 'லிச்சென்ஸ்டீன் குடிமகன்'],
['code' => 'LT', 'name' => 'Lithuanian', 'hi' => 'लिथुआनियाई', 'sw' => 'Mlituania', 'tl' => 'Lithuanian', 'ta' => 'லிதுவேனியன்'],
['code' => 'LU', 'name' => 'Luxembourger', 'hi' => 'लक्ज़मबर्ग का', 'sw' => 'Mluxembourg', 'tl' => 'Luxembourger', 'ta' => 'லக்சம்பர்கர்'],
['code' => 'MO', 'name' => 'Macanese', 'hi' => 'मकाऊ का', 'sw' => 'Mmacao', 'tl' => 'Macanese', 'ta' => 'மக்கானீஸ்'],
['code' => 'MK', 'name' => 'Macedonian', 'hi' => 'मैसिडोनियाई', 'sw' => 'Mmasedonia', 'tl' => 'Macedonian', 'ta' => 'மாசிடோனியன்'],
['code' => 'MG', 'name' => 'Malagasy', 'hi' => 'मालागासी', 'sw' => 'Mmalagasi', 'tl' => 'Malagasy', 'ta' => 'மலகாசி'],
['code' => 'MW', 'name' => 'Malawian', 'hi' => 'मलावी का', 'sw' => 'Mmalawi', 'tl' => 'Malawian', 'ta' => 'மலாவி'],
['code' => 'MY', 'name' => 'Malaysian', 'hi' => 'मलेशियाई', 'sw' => 'Mmalaysia', 'tl' => 'Malaysian', 'ta' => 'மலேசியன்'],
['code' => 'MV', 'name' => 'Maldivian', 'hi' => 'मालदीव का', 'sw' => 'Mmaldivi', 'tl' => 'Maldivian', 'ta' => 'மாலத்தீவியர்'],
['code' => 'ML', 'name' => 'Malian', 'hi' => 'माली का', 'sw' => 'Mmali', 'tl' => 'Malian', 'ta' => 'மாலியன்'],
['code' => 'MT', 'name' => 'Maltese', 'hi' => 'माल्टीज़', 'sw' => 'Mmalta', 'tl' => 'Maltese', 'ta' => 'மால்டீஸ்'],
['code' => 'MH', 'name' => 'Marshallese', 'hi' => 'मार्शलीज़', 'sw' => 'Mmarshall', 'tl' => 'Marshallese', 'ta' => 'மார்ஷலீஸ்'],
['code' => 'MQ', 'name' => 'Martiniquais', 'hi' => 'मार्टीनिक का', 'sw' => 'Mmartinique', 'tl' => 'Martiniquais', 'ta' => 'மார்டினிகாஸ்'],
['code' => 'MR', 'name' => 'Mauritanian', 'hi' => 'मॉरिटानिया का', 'sw' => 'Mmoritania', 'tl' => 'Mauritanian', 'ta' => 'மௌரிடானியன்'],
['code' => 'MU', 'name' => 'Mauritian', 'hi' => 'मॉरीशस का', 'sw' => 'Mmorisi', 'tl' => 'Mauritian', 'ta' => 'மொரிஷியன்'],
['code' => 'MX', 'name' => 'Mexican', 'hi' => 'मैक्सिकन', 'sw' => 'Mmeksiko', 'tl' => 'Mexican', 'ta' => 'மெக்சிகன்'],
['code' => 'FM', 'name' => 'Micronesian', 'hi' => 'माइक्रोनेशियन', 'sw' => 'Mmikronesia', 'tl' => 'Micronesian', 'ta' => 'மைக்ரோனேசியன்'],
['code' => 'MD', 'name' => 'Moldovan', 'hi' => 'मोल्दोवन', 'sw' => 'Mmoldova', 'tl' => 'Moldovan', 'ta' => 'மால்டோவன்'],
['code' => 'MC', 'name' => 'Monegasque', 'hi' => 'मोनेगास्क', 'sw' => 'Mmonaco', 'tl' => 'Monegasque', 'ta' => 'மொனகாஸ்க்'],
['code' => 'MN', 'name' => 'Mongolian', 'hi' => 'मंगोलियाई', 'sw' => 'Mmongolia', 'tl' => 'Mongolian', 'ta' => 'மங்கோலியன்'],
['code' => 'ME', 'name' => 'Montenegrin', 'hi' => 'मोंटेनेग्रिन', 'sw' => 'Mmontenegro', 'tl' => 'Montenegrin', 'ta' => 'மாண்டினீக்ரின்'],
['code' => 'MS', 'name' => 'Montserratian', 'hi' => 'मोंटसेराट का', 'sw' => 'Mmontserrat', 'tl' => 'Montserratian', 'ta' => 'மான்ட்செராட்டியன்'],
['code' => 'MA', 'name' => 'Moroccan', 'hi' => 'मोरक्कन', 'sw' => 'Mmoroko', 'tl' => 'Moroccan', 'ta' => 'மொராக்கோ'],
['code' => 'LS', 'name' => 'Mosotho', 'hi' => 'लेसोथो का', 'sw' => 'Msotho', 'tl' => 'Mosotho', 'ta' => 'மொசோதோ'],
['code' => 'MZ', 'name' => 'Mozambican', 'hi' => 'मोज़ाम्बिक का', 'sw' => 'Msumbiji', 'tl' => 'Mozambican', 'ta' => 'மொசாம்பிகன்'],
['code' => 'NA', 'name' => 'Namibian', 'hi' => 'नामीबिया का', 'sw' => 'Mnamibia', 'tl' => 'Namibian', 'ta' => 'நமீபியன்'],
['code' => 'NR', 'name' => 'Nauruan', 'hi' => 'नाउरू का', 'sw' => 'Mnauru', 'tl' => 'Nauruan', 'ta' => 'நவூருவன்'],
['code' => 'NP', 'name' => 'Nepalese', 'hi' => 'नेपाली', 'sw' => 'Mnepali', 'tl' => 'Nepalese', 'ta' => 'நேபாளியர்'],
['code' => 'NZ', 'name' => 'New Zealander', 'hi' => 'न्यूजीलैंड का', 'sw' => 'Mnyuzilandi', 'tl' => 'New Zealander', 'ta' => 'நியூசிலாந்தர்'],
['code' => 'NI', 'name' => 'Nicaraguan', 'hi' => 'निकारागुआ का', 'sw' => 'Mnikaragua', 'tl' => 'Nicaraguan', 'ta' => 'நிகரகுவான்'],
['code' => 'NG', 'name' => 'Nigerian', 'hi' => 'नाइजीरियाई', 'sw' => 'Mnaigeria', 'tl' => 'Nigerian', 'ta' => 'நைஜீரியன்'],
['code' => 'NE', 'name' => 'Nigerien', 'hi' => 'नाइजर का', 'sw' => 'Mniger', 'tl' => 'Nigerien', 'ta' => 'நைஜீரியன் (நைஜர்)'],
['code' => 'NU', 'name' => 'Niuean', 'hi' => 'नियू का', 'sw' => 'Mniue', 'tl' => 'Niuean', 'ta' => 'நியூயன்'],
['code' => 'KP', 'name' => 'North Korean', 'hi' => 'उत्तर कोरियाई', 'sw' => 'Mwakorea Kaskazini', 'tl' => 'North Korean', 'ta' => 'வட கொரியர்'],
['code' => 'GB-NIR', 'name' => 'Northern Irish', 'hi' => 'उत्तरी आयरिश', 'sw' => 'Miairishi wa Kaskazini', 'tl' => 'Northern Irish', 'ta' => 'வடக்கு ஐரிஷ்'],
['code' => 'NO', 'name' => 'Norwegian', 'hi' => 'नॉर्वेजियन', 'sw' => 'Mnorwei', 'tl' => 'Norwegian', 'ta' => 'நோர்வேஜியன்'],
['code' => 'OM', 'name' => 'Omani', 'hi' => 'ओमानी', 'sw' => 'Momani', 'tl' => 'Omani', 'ta' => 'ஓமானி'],
['code' => 'PK', 'name' => 'Pakistani', 'hi' => 'पाकिस्तानी', 'sw' => 'Mpakistani', 'tl' => 'Pakistani', 'ta' => 'பாகிஸ்தானி'],
['code' => 'PW', 'name' => 'Palauan', 'hi' => 'पलाऊ का', 'sw' => 'Mpalau', 'tl' => 'Palauan', 'ta' => 'பாலோவன்'],
['code' => 'PS', 'name' => 'Palestinian', 'hi' => 'फिलिस्तीनी', 'sw' => 'Mpalestina', 'tl' => 'Palestinian', 'ta' => 'பாலஸ்தீனியர்'],
['code' => 'PA', 'name' => 'Panamanian', 'hi' => 'पनामा का', 'sw' => 'Mpanama', 'tl' => 'Panamanian', 'ta' => 'பனமேனியன்'],
['code' => 'PG', 'name' => 'Papua New Guinean', 'hi' => 'पापुआ न्यू गिनी का', 'sw' => 'Mpapua', 'tl' => 'Papua New Guinean', 'ta' => 'பப்புவா நியூ கினியன்'],
['code' => 'PY', 'name' => 'Paraguayan', 'hi' => 'पराग्वे का', 'sw' => 'Mparagwai', 'tl' => 'Paraguayan', 'ta' => 'பராகுவேயன்'],
['code' => 'PE', 'name' => 'Peruvian', 'hi' => 'पेरू का', 'sw' => 'Mperu', 'tl' => 'Peruvian', 'ta' => 'பெருவியன்'],
['code' => 'PN', 'name' => 'Pitcairn Islander', 'hi' => 'पिटकेर्न द्वीप समूह का', 'sw' => 'Mpitcairn', 'tl' => 'Pitcairn Islander', 'ta' => 'பிட்கேர்ன் தீவுவாசி'],
['code' => 'PL', 'name' => 'Polish', 'hi' => 'पोलिश', 'sw' => 'Mpolandi', 'tl' => 'Polish', 'ta' => 'போலிஷ்'],
['code' => 'PT', 'name' => 'Portuguese', 'hi' => 'पुर्तगाली', 'sw' => 'Mreno', 'tl' => 'Portuguese', 'ta' => 'போர்த்துகீசியர்'],
['code' => 'PRY', 'name' => 'Prydeinig', 'hi' => 'प्राइडेनिग (ब्रिटिश)', 'sw' => 'Mwananchi wa Prydain', 'tl' => 'Prydeinig', 'ta' => 'பிரிட்டிஷ் (வெல்ஷ்)'],
['code' => 'PR', 'name' => 'Puerto Rican', 'hi' => 'प्यूर्टो रिको का', 'sw' => 'Mpuertoriko', 'tl' => 'Puerto Rican', 'ta' => 'போர்ட்டோ ரிகான்'],
['code' => 'QA', 'name' => 'Qatari', 'hi' => 'कतरी', 'sw' => 'Mkatari', 'tl' => 'Qatari', 'ta' => 'கத்தாரி'],
['code' => 'RO', 'name' => 'Romanian', 'hi' => 'रोमानियाई', 'sw' => 'Mromania', 'tl' => 'Romanian', 'ta' => 'ரோமானியன்'],
['code' => 'RU', 'name' => 'Russian', 'hi' => 'रूसी', 'sw' => 'Mrusi', 'tl' => 'Ruso', 'ta' => 'ரஷ்யர்'],
['code' => 'RW', 'name' => 'Rwandan', 'hi' => 'रवांडा का', 'sw' => 'Mnyarwanda', 'tl' => 'Rwandan', 'ta' => 'ருவாண்டன்'],
['code' => 'SV', 'name' => 'Salvadorean', 'hi' => 'अल साल्वाडोर का', 'sw' => 'Msalvador', 'tl' => 'Salvadorean', 'ta' => 'சால்வடோரியன்'],
['code' => 'SM', 'name' => 'Sammarinese', 'hi' => 'सैन मैरिनो का', 'sw' => 'Msanmarino', 'tl' => 'Sammarinese', 'ta' => 'சான் மரினீஸ்'],
['code' => 'WS', 'name' => 'Samoan', 'hi' => 'समोआ का', 'sw' => 'Msamoa', 'tl' => 'Samoan', 'ta' => 'சமோவன்'],
['code' => 'ST', 'name' => 'Sao Tomean', 'hi' => 'साओ टोम का', 'sw' => 'Msaotome', 'tl' => 'Sao Tomean', 'ta' => 'சாவோ டோமியன்'],
['code' => 'SA', 'name' => 'Saudi Arabian', 'hi' => 'सऊदी अरब का', 'sw' => 'Msaudi', 'tl' => 'Saudi', 'ta' => 'சவுதி அரேபியன்'],
['code' => 'GB-SCT', 'name' => 'Scottish', 'hi' => 'स्कॉटिश', 'sw' => 'Mskochi', 'tl' => 'Scottish', 'ta' => 'ஸ்காட்டிஷ்'],
['code' => 'SN', 'name' => 'Senegalese', 'hi' => 'सेनेगल का', 'sw' => 'Msenegali', 'tl' => 'Senegalese', 'ta' => 'செனகலீஸ்'],
['code' => 'RS', 'name' => 'Serbian', 'hi' => 'सर्बियाई', 'sw' => 'Mserbia', 'tl' => 'Serbian', 'ta' => 'செர்பியன்'],
['code' => 'SC', 'name' => 'Citizen of Seychelles', 'hi' => 'सेशेल्स का नागरिक', 'sw' => 'Mshelisheli', 'tl' => 'Citizen of Seychelles', 'ta' => 'சீஷெல்ஸ் குடிமகன்'],
['code' => 'SL', 'name' => 'Sierra Leonean', 'hi' => 'सिएरा लियोन का', 'sw' => 'Msieraleoni', 'tl' => 'Sierra Leonean', 'ta' => 'சியரா லியோனியன்'],
['code' => 'SG', 'name' => 'Singaporean', 'hi' => 'सिंगापुर का', 'sw' => 'Msingapuri', 'tl' => 'Singaporean', 'ta' => 'சிங்கப்பூரியர்'],
['code' => 'SK', 'name' => 'Slovak', 'hi' => 'स्लोवाक', 'sw' => 'Mslovakia', 'tl' => 'Slovak', 'ta' => 'ஸ்லோவாக்'],
['code' => 'SI', 'name' => 'Slovenian', 'hi' => 'स्लोवेनियाई', 'sw' => 'Mslovenia', 'tl' => 'Slovenian', 'ta' => 'ஸ்லோவேனியன்'],
['code' => 'SB', 'name' => 'Solomon Islander', 'hi' => 'सोलोमन द्वीप का', 'sw' => 'Msolomon', 'tl' => 'Solomon Islander', 'ta' => 'சாலமன் தீவுவாசி'],
['code' => 'SO', 'name' => 'Somali', 'hi' => 'सोमाली', 'sw' => 'Msomali', 'tl' => 'Somali', 'ta' => 'சோமாலி'],
['code' => 'ZA', 'name' => 'South African', 'hi' => 'दक्षिण अफ्रीकी', 'sw' => 'Mswazi', 'tl' => 'South African', 'ta' => 'தென்னாப்பிரிக்கர்'],
['code' => 'KR', 'name' => 'South Korean', 'hi' => 'दक्षिण कोरियाई', 'sw' => 'Mwakorea Kusini', 'tl' => 'South Korean', 'ta' => 'தென் கொரியர்'],
['code' => 'SS', 'name' => 'South Sudanese', 'hi' => 'दक्षिण सूडानी', 'sw' => 'Msudani Kusini', 'tl' => 'South Sudanese', 'ta' => 'தெற்கு சூடானியர்'],
['code' => 'ES', 'name' => 'Spanish', 'hi' => 'स्पैनिश', 'sw' => 'Mhispania', 'tl' => 'Kastila', 'ta' => 'ஸ்பானிஷ்'],
['code' => 'LK', 'name' => 'Sri Lankan', 'hi' => 'श्रीलंकाई', 'sw' => 'Msri Lanka', 'tl' => 'Sri Lankan', 'ta' => 'இலங்கை'],
['code' => 'SH', 'name' => 'St Helenian', 'hi' => 'सेंट हेलेना का', 'sw' => 'Mtakatifu Helena', 'tl' => 'St Helenian', 'ta' => 'செயின்ட் ஹெலினியன்'],
['code' => 'LC', 'name' => 'St Lucian', 'hi' => 'सेंट लूसिया का', 'sw' => 'Mtakatifu Lusia', 'tl' => 'St Lucian', 'ta' => 'செயின்ட் லூசியன்'],
['code' => 'ST-L', 'name' => 'Stateless', 'hi' => 'राज्यविहीन', 'sw' => 'Bila Uraia', 'tl' => 'Stateless', 'ta' => 'நாடற்றவர்'],
['code' => 'SD', 'name' => 'Sudanese', 'hi' => 'सूडानी', 'sw' => 'Msudani', 'tl' => 'Sudanese', 'ta' => 'சூடானியர்'],
['code' => 'SR', 'name' => 'Surinamese', 'hi' => 'सूरीनाम का', 'sw' => 'Msuriname', 'tl' => 'Surinamese', 'ta' => 'சுரிநாமீஸ்'],
['code' => 'SZ', 'name' => 'Swazi', 'hi' => 'स्वाजी', 'sw' => 'Mswazi', 'tl' => 'Swazi', 'ta' => 'சுவாசி'],
['code' => 'SE', 'name' => 'Swedish', 'hi' => 'स्वीडिश', 'sw' => 'Mswidi', 'tl' => 'Swedish', 'ta' => 'சுவீடிஷ்'],
['code' => 'CH', 'name' => 'Swiss', 'hi' => 'स्विस', 'sw' => 'Mswisi', 'tl' => 'Swiss', 'ta' => 'சுவிஸ்'],
['code' => 'SY', 'name' => 'Syrian', 'hi' => 'सीरियाई', 'sw' => 'Msiria', 'tl' => 'Syrian', 'ta' => 'சிரியன்'],
['code' => 'TW', 'name' => 'Taiwanese', 'hi' => 'ताइवानी', 'sw' => 'Mtaiwan', 'tl' => 'Taiwanese', 'ta' => 'தைவானியர்'],
['code' => 'TJ', 'name' => 'Tajik', 'hi' => 'ताजिक', 'sw' => 'Mtajiki', 'tl' => 'Tajik', 'ta' => 'தஜிக்'],
['code' => 'TZ', 'name' => 'Tanzanian', 'hi' => 'तंजानिया का', 'sw' => 'Mtanzania', 'tl' => 'Tanzanian', 'ta' => 'தான்சானியன்'],
['code' => 'TH', 'name' => 'Thai', 'hi' => 'थाई', 'sw' => 'Mthai', 'tl' => 'Thai', 'ta' => 'தாய்லாந்தியர்'],
['code' => 'TG', 'name' => 'Togolese', 'hi' => 'टोगो का', 'sw' => 'Mtogo', 'tl' => 'Togolese', 'ta' => 'டோகோலீஸ்'],
['code' => 'TO', 'name' => 'Tongan', 'hi' => 'टोंगा का', 'sw' => 'Mtonga', 'tl' => 'Tongan', 'ta' => 'தொங்கன்'],
['code' => 'TT', 'name' => 'Trinidadian', 'hi' => 'त्रिनिदाद का', 'sw' => 'Mtrinidad', 'tl' => 'Trinidadian', 'ta' => 'திரினிடாடியன்'],
['code' => 'TA-T', 'name' => 'Tristanian', 'hi' => 'ट्रिस्टन का', 'sw' => 'Mtristan', 'tl' => 'Tristanian', 'ta' => 'டிரிஸ்டானியன்'],
['code' => 'TN', 'name' => 'Tunisian', 'hi' => 'ट्यूनीशियाई', 'sw' => 'Mtunisia', 'tl' => 'Tunisian', 'ta' => 'துனிசியன்'],
['code' => 'TR', 'name' => 'Turkish', 'hi' => 'तुर्की', 'sw' => 'Mturki', 'tl' => 'Turko', 'ta' => 'துருக்கியர்'],
['code' => 'TM', 'name' => 'Turkmen', 'hi' => 'तुर्कमेन', 'sw' => 'Mturkmeni', 'tl' => 'Turkmen', 'ta' => 'துருக்மேனியர்'],
['code' => 'TC', 'name' => 'Turks and Caicos Islander', 'hi' => 'तुर्क और कैकोस का', 'sw' => 'Mkaazi wa Turks na Caicos', 'tl' => 'Turks and Caicos Islander', 'ta' => 'டர்க்ஸ் மற்றும் கைகோஸ் தீவுவாசி'],
['code' => 'TV', 'name' => 'Tuvaluan', 'hi' => 'तुवालु का', 'sw' => 'Mtuvalu', 'tl' => 'Tuvaluan', 'ta' => 'துவாலுவன்'],
['code' => 'UG', 'name' => 'Ugandan', 'hi' => 'युगांडा का', 'sw' => 'Mganda', 'tl' => 'Ugandan', 'ta' => 'உகாண்டா'],
['code' => 'UA', 'name' => 'Ukrainian', 'hi' => 'यूक्रेनी', 'sw' => 'Myukraine', 'tl' => 'Ukrainian', 'ta' => 'உக்ரைனியன்'],
['code' => 'UY', 'name' => 'Uruguayan', 'hi' => 'उरुग्वे का', 'sw' => 'Murugwai', 'tl' => 'Uruguayan', 'ta' => 'உருகுவேயன்'],
['code' => 'UZ', 'name' => 'Uzbek', 'hi' => 'उज़्बेक', 'sw' => 'Muzbeki', 'tl' => 'Uzbek', 'ta' => 'உஸ்பெக்'],
['code' => 'VA', 'name' => 'Vatican citizen', 'hi' => 'वेटिकन का नागरिक', 'sw' => 'Mwananchi wa Vatican', 'tl' => 'Vatican citizen', 'ta' => 'வத்திக்கான் குடிமகன்'],
['code' => 'VU', 'name' => 'Citizen of Vanuatu', 'hi' => 'वानुअतु का नागरिक', 'sw' => 'Mwananchi wa Vanuatu', 'tl' => 'Citizen of Vanuatu', 'ta' => 'வனுவாட்டு குடிமகன்'],
['code' => 'VE', 'name' => 'Venezuelan', 'hi' => 'वेनेजुएला का', 'sw' => 'Mvenezuela', 'tl' => 'Venezuelan', 'ta' => 'வெனிசுலான்'],
['code' => 'VN', 'name' => 'Vietnamese', 'hi' => 'वियतनामी', 'sw' => 'Mvietnam', 'tl' => 'Vietnamese', 'ta' => 'வியட்நாமியர்'],
['code' => 'VC', 'name' => 'Vincentian', 'hi' => 'विन्सेंटियन', 'sw' => 'Mvincent', 'tl' => 'Vincentian', 'ta' => 'வின்சென்டியன்'],
['code' => 'WF', 'name' => 'Wallisian', 'hi' => 'वालिसियन', 'sw' => 'Mwallis', 'tl' => 'Wallisian', 'ta' => 'வாலிசியன்'],
['code' => 'GB-WLS', 'name' => 'Welsh', 'hi' => 'वेल्श', 'sw' => 'Mwelshi', 'tl' => 'Welsh', 'ta' => 'வெல்ஷ்'],
['code' => 'YE', 'name' => 'Yemeni', 'hi' => 'यमनी', 'sw' => 'Myemeni', 'tl' => 'Yemeni', 'ta' => 'யேமனி'],
['code' => 'ZM', 'name' => 'Zambian', 'hi' => 'जाम्बियन', 'sw' => 'Mzambia', 'tl' => 'Zambian', 'ta' => 'சாம்பியன்'],
['code' => 'ZW', 'name' => 'Zimbabwean', 'hi' => 'जिम्बाब्वे का', 'sw' => 'Mzimbabwe', 'tl' => 'Zimbabwean', 'ta' => 'ஜிம்பாப்வேயன்']
];
$list = [];
foreach ($rawNationalities as $item) {
$list[] = [
'code' => $item['code'],
'name' => $item[$lang] ?? $item['name'],
];
}
$search = strtolower($request->input('search') ?? $request->input('q') ?? '');
if ($search !== '') {
$list = array_filter($list, function ($item) use ($search) {
return stripos($item['name'], $search) !== false || stripos($item['code'], $search) !== false;
});
$list = array_values($list);
}
// Apply Pagination
$page = (int) $request->input('page', 1);
$perPage = (int) $request->input('per_page', 15);
$total = count($list);
$offset = ($page - 1) * $perPage;
$paginatedList = array_slice($list, $offset, $perPage);
return response()->json([
'success' => true,
'data' => [
'nationalities' => $paginatedList,
'pagination' => [
'total' => $total,
'per_page' => $perPage,
'current_page' => $page,
'last_page' => max(1, (int) ceil($total / $perPage)),
]
],
], 200);
}
}