approached/laravel-date-international
Laravel Date International is a Laravel package for locale-aware date formatting. It helps present dates using regional conventions, with Carbon and Blade integration so dates read naturally for users across different languages and regions.
Install (Laravel 5.5+ auto-discovers the provider):
composer require approached/laravel-date-international
For Laravel ≤5.4, manually register Approached\LaravelDateInternational\DateInternationalServiceProvider in config/app.php and add the facade alias (commonly DateInternational).
Publish the config so you can see the locale/dictionary map:
php artisan vendor:publish --provider="Approached\LaravelDateInternational\DateInternationalServiceProvider"
The published config/date-international.php is the first file to open — it tells you which locales are supported and how month/day tokens are mapped.
Read src/ before the README. This is a 10-star, archived package; the source is short and is the only reliable documentation. Look at the facade class for the public methods (transform, translate, setLocale-style calls are the typical surface) and the config loader.
First use case — render a localized date string in a Blade view:
{{ DateInternational::locale('ru')->transform($post->published_at) }}
Start with a single hard-coded locale to confirm the config dictionary loads, then wire the locale to app()->getLocale().
Config-driven dictionaries. Treat the package as a lookup table, not a date library. Parse/format with Carbon, then hand the formatted string to the transformer for month/day-name substitution. Keep your own locale files if you need languages the package doesn't ship.
Blade directive / helper wrapper. Because package methods can change (archived = no BC guarantees), wrap them:
// app/Support/DateFormatter.php
public static function localize($date, ?string $locale = null): string
{
return app('date-international')
->locale($locale ?? app()->getLocale())
->transform(Carbon::parse($date));
}
One wrapper means a later swap to Carbon's native translatedFormat() is a one-file change.
Resolve locale from the request, not the package. Use Laravel's App::setLocale() / app()->getLocale() in middleware and pass it in. Don't let the package guess from HTTP_ACCEPT_LANGUAGE — you lose control and testability.
Compose with Carbon for parsing/arithmetic. Let Carbon handle addDays, timezones, and diffing; use this package only for the final string transformation. This keeps behavior predictable and makes a future migration trivial.
Cache the config-aware instance if you call it in loops (e.g., rendering 50 rows). Resolve once per request via the container rather than new-ing per row.
Validation: if locales come from user input, validate against array_keys(config('date-international.locales')) (or whatever the config key is named) with a Rule::in().
Carbon::parse($d)->locale('fr')->translatedFormat('j F Y') does the same job natively and is maintained. Evaluate this package only if you specifically need its dictionary format; otherwise prefer Carbon.en vs en_US vs en-GB will silently return the original string. Log or assert when a locale isn't found rather than failing open.php artisan config:clear (and config:cache in prod). Stale cached config is a common "why didn't my translation change" cause — especially in CI where caches persist between steps.transform() accepts strings, 01/02/2020 is ambiguous. Always pass a Carbon instance or a strict ISO string to remove the guesswork.config('app.timezone') and convert with Carbon first.diffForHumans() with a locale, or a dedicated package.Carbon::setTestNow() and assert exact output per locale; snapshot tests for each supported language catch accidental format drift.DateInternational or similar, alias it explicitly ('LocalizedDate' => ...) to avoid resolving the wrong binding.How can I help you explore Laravel packages today?