Astrotomic / laravel-translatable

A Laravel package for multilingual models
https://docs.astrotomic.info/laravel-translatable/
MIT License
1.23k stars 156 forks source link

Fallback not working? #256

Closed johgh closed 2 years ago

johgh commented 2 years ago

I have this in my config file:

return [ 'locales' => [ 'en', 'es', ], 'locale_separator' => '-', 'locale' => null, 'use_fallback' => true, 'use_property_fallback' => false, 'fallback_locale' => null,

In DB I only have 'es' translations. Then I try this in artisan tinker:

$bio = Bio::first(); => App\Models\Bio {#4523 id: 1, (...)

$bio->translate('en') => null

app()->setLocale('en') $bio->role => null

Why is not retrieving spanish translation as fallback? (I set fallback_locale to null as docs say: "If you do not want to define the default fallback locale but just get the first (in order of configuration) defined one you can set fallback_locale to null.")

github-actions[bot] commented 2 years ago

This issue is stale because it has been open 21 days with no activity. Remove stale label or comment or this will be closed in 7 days

shelleychristie commented 3 months ago

I have this problem too. Did you ever figure it out, or is this a bug? I also tried $bio->translate('en', true)->attribute but it still isn't working even with the $withFallback parameter set to true.

johgh commented 3 months ago

I don't remember I used this package while ago, i just found this in my notes:

$post = Post::whereTranslation('slug', $slug)->first();

i'm not sure if it is what you're asking for...

On Fri, Jun 7, 2024 at 6:16 AM shelleychristie @.***> wrote:

I have this problem too. Did you ever figure it out, or is this a bug? I also tried $bio->translate('en', true)->attribute but it still isn't working even with the $withFallback parameter set to true.

— Reply to this email directly, view it on GitHub https://github.com/Astrotomic/laravel-translatable/issues/256#issuecomment-2153883088, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACADOEQZWUTXEYFE6EFG3PLZGEXY5AVCNFSM6AAAAABI55D27WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJTHA4DGMBYHA . You are receiving this because you authored the thread.Message ID: @.***>

shelleychristie commented 3 months ago

Here is my workaround for this. Hope it helps someone in the future, and please leave a comment if you have better ways!

The problem comes from Translatable's getTranslation() function

public function getTranslation(?string $locale = null, bool $withFallback = null): ?Model
    {
        $configFallbackLocale = $this->getFallbackLocale();
        $locale = $locale ?: $this->locale();
        $withFallback = $withFallback === null ? $this->useFallback() : $withFallback;
        ..etc...

wherein $this->getFallbackLocale() returns config('app.fallback_locale'). On my app, my app.fallback_locale is set to 'en' while my translatable.fallback_locale is set to null. Because $configFallbackLocale is set to 'en', it never gets to the point of the function where it goes through your locales one by one in order to get an available translation, and instead goes for the English translation which doesn't exist and returns null.

To overcome this, I overrided the getTranslation() function (in a separate class that extends Translatable) and put in a new function in place of the old getFallbackLocale()

// new function
protected function getFallbackLocaleConfig(?string $locale = null): ?string
    {
        if ($locale && $this->getLocalesHelper()->isLocaleCountryBased($locale)) {
            if ($fallback = $this->getLocalesHelper()->getLanguageFromCountryBasedLocale($locale)) {
                return $fallback;
            }
        }

        // change from config(app.fallback_locale)
        return config('translatable.fallback_locale');
    }

// override vendor function to incorporate new getFallbackLocaleConfig()
    public function getTranslation(?string $locale = null, bool $withFallback = null): ?Model
    {
        $configFallbackLocale = $this->getFallbackLocaleConfig(); // custom fallbacklocale function
        $locale = $locale ?: $this->locale();
       .....etc....