ianm/iso-639
Provides ISO 639 language code data for PHP, mapping codes to language names so apps can display, validate, and look up locale or language identifiers. A lightweight dependency used by Flarum extensions for consistent language handling.
composer require ianm/iso-639. There is no service provider, no publishable config, no migrations, and no facade — it's a pure data library. Nothing to register in config/app.php.vendor/ianm/iso-639/src/. The whole package is effectively one class wrapping a hard-coded ['en' => 'English', 'fr' => 'Français', ...] map derived from Wikipedia's ISO 639-1 list. Read the file once to confirm the namespace and method names (they're usually exposed as static lookups like getName() / getNames()); the examples below use that shape.php artisan tinker:
\IanM\ISO639\ISO639::getName('en'); // "English"
\IanM\ISO639\ISO639::getName('zz'); // expect null/empty — verify behavior
users.locale, posts.language, a settings JSON column) and need to render a human-readable name in a profile page, settings screen, or admin table — without maintaining your own 180-entry array.Blade rendering with a guard. The most common day-to-day use. Never assume the stored code is valid:
{{ \IanM\ISO639\ISO639::getName($user->locale) ?? $user->locale }}
Model accessor. Keep the view dumb and the lookup centralized:
public function getLocaleNameAttribute(): string
{
return ISO639::getName($this->locale) ?? $this->locale;
}
Select dropdown for settings. Build from the package's full map so it never drifts from your validation source:
$languages = ISO639::getNames(); // ['en' => 'English', ...]
return view('settings.profile', compact('languages'));
@foreach ($languages as $code => $name)
<option value="{{ $code }}" @selected(old('locale', $user->locale) === $code)>{{ $name }}</option>
@endforeach
Form request validation. Reuse the same map as the source of truth instead of hard-coding in:en,fr,de:
'locale' => ['required', 'string', Rule::in(array_keys(ISO639::getNames()))],
Bulk mapping. For API responses or CSV exports, map a collection of codes with a fallback:
$names = $codes->map(fn ($code) => ISO639::getName($code) ?? $code);
Localization bridge. If your UI is multilingual, treat the package as a fallback and prefer your own translation keys (__('languages.en')) so names render in the user's interface language, not English:
$name = trans()->has("languages.{$code}")
? __("languages.{$code}")
: ISO639::getName($code);
Wrapper class. Because the API surface is tiny, wrap it behind your own App\Support\Languages helper. That gives you one place to normalize input, add caching, and swap the implementation later without touching every Blade file.
composer.json, and know that a fallback path exists: the source is one array you can copy into your own config/languages.php in ten minutes if the package is abandoned.strtolower() and strip any region suffix. en_US, en-GB, and pt_BR are not ISO 639-1 codes; split on -/_ and pass the language segment only.null, an empty string, or throw depending on how the lookup is implemented. Verify once in tinker, then always use ?? with the raw code as fallback so a bad value never blanks the UI.he/iw, id/in, yi/ji) and some codes have multiple valid names. Check what the package returns for your existing data before assuming parity with any array you're replacing.en, fr) so a future composer update doesn't break CI.Rule, a Blade component, a cast — you build yourself; consider that a feature, since there's nothing to boot or publish.getName() calls are already cheap. Cache only if you're resolving thousands of codes per request.en_US → "English (United States)", plural rules, or display-name-in-that-language, move to symfony/intl: it does everything here plus regions and native names (Locale::getDisplayLanguage('fr', 'fr') → "français"). This package is the right tool for exactly one job: 2-letter code → English name.How can I help you explore Laravel packages today?