NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

The FallbackMode enum drives every read that uses fallback — property access, getTranslation() with fallback on, and serialization:

ModeConfig valueResolution
FallbackMode::NonenoneExact requested locale only — null when it’s missing.
FallbackMode::FallbackfallbackExact locale, then the configured fallback locale.
FallbackMode::AnyanyExact locale, then the fallback locale, then the first available value — supported locales in order, then any other stored locale alphabetically. The default — content never renders blank.
// Stored: name = {"sk": "Investovanie"}, fallback_locale = en, app locale = de

// FallbackMode::Any (default)
$topic->name;                                // 'Investovanie' — first available value

// FallbackMode::Fallback or FallbackMode::None
$topic->name;                                // null

// Regardless of the mode
$topic->getTranslation('name', 'de', false); // null — fallback switched off
$topic->translatedOrNull('name');            // null — exact app locale only

Any’s last step walks the supported locales in order, then any other stored locale alphabetically. The pick never depends on how the database orders JSON keys, so a row renders the same language on every engine and before and after a reload.

Cross-locale disclosure with Any

Any is the shipped default so content never renders blank. The tradeoff: when both the requested and the fallback locale are empty, Any renders the first available locale’s value — so content you deliberately left untranslated for a locale can still appear in another language. If some content is legally or compliance-gated per locale, switch to Fallback (or None) globally via TRANSLATABLE_FALLBACK or the config, or per model:

use RoundlyConsulting\Translatable\Enums\FallbackMode;

protected ?FallbackMode $translatableFallbackMode = FallbackMode::Fallback;
protected ?string $translatableFallbackLocale = 'en';

An unrecognised value in translatable.fallback resolves to Any. FallbackMode uses the Helpers trait from enums-for-laravel, so that package’s enum helpers are available on it.

Resolving a raw map

Translatable::resolve() runs the same resolution a model read uses, for a raw map you hold outside a model — a cached payload, an API response, a config array. The locale defaults to the current one, the mode and fallback locale to the configured ones. Blank values never win — null, '', booleans, arrays and objects are skipped, ints and floats are cast to strings — so a messy map resolves and never throws:

use RoundlyConsulting\Translatable\Enums\FallbackMode;
use RoundlyConsulting\Translatable\Facades\Translatable;

$map = ['en' => 'Investing', 'sk' => 'Investovanie']; // a cached payload, an API response, a config array

app()->setLocale('sk');
Translatable::resolve($map);                          // 'Investovanie' — current locale, configured chain
Translatable::resolve($map, 'de');                    // 'Investing' — falls back to fallback_locale (en)
Translatable::resolve($map, 'de', FallbackMode::None); // null — exact locale only
Translatable::resolve($map, 'de', FallbackMode::Fallback, fallbackLocale: 'sk'); // 'Investovanie'

// A messy map resolves, it never throws:
Translatable::resolve(['en' => null, 'sk' => 'Ahoj'], 'de'); // 'Ahoj'
Translatable::resolve(['sk' => 5], 'de');                   // '5'

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.