Fallback modes
The FallbackMode enum drives every read that uses fallback — property access, getTranslation() with fallback on, and serialization:
| Mode | Config value | Resolution |
|---|---|---|
FallbackMode::None | none | Exact requested locale only — null when it’s missing. |
FallbackMode::Fallback | fallback | Exact locale, then the configured fallback locale. |
FallbackMode::Any | any | Exact 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 onlyAny’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 cryptoBy 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.