skip to Main Content

I am using the laravel-translatable library for developing a multi-language web system. In this web application, there is no front-end, and the data is read and written through APIs. The problem I am facing is that I cannot fetch all the records stored in the database in one or more languages, for example, all records from the ‘blog’ table where the title is in English and French. The library documentation does not explicitly mention this, and I could not solve the issue with the codes I have tested. The following are the code examples I tried, but none of them resolved my problem:

//1)
Route::get('/', function () {
    return response()->json(
        DB::table('blogs')
        ->get()
        ->filter(function ($blog) {
            return $blog->getTranslations('title', ['en']);
        })
    );
});

//2)
Route::get('/', function () {
    return response()->json(
        DB::table('blogs')
        ->get()
        ->filter(function ($blog) {
            return collect(json_decode($blog->title))->has('en');
        })
    );
});

//3)
Route::get('/', function () {
    return response()->json(Blog::titleEqualsEn()->get(), 200);
});

blog migration:

public function up(): void
{
    Schema::create('blogs', function (Blueprint $table) {
        $table->id();
        $table->json('title');
        $table->json('content');
    });
}

2

Answers


  1. It looks like that library is setting different languages in JSON format, creating different keys for different languages. So presumably you could query for all blogs with an English title like:

    Route::get('/', function () {
        return response()->json(
            DB::table('blogs')
            ->whereNotNull('title->en')
            ->get()
        );
    });
    

    According to their documentation, if you’re using MaraiDB 10.2.3 or above you’ll need to use a raw version of the query such like

    Route::get('/', function () {
            return response()->json(
                DB::table('blogs')
                ->whereRaw("JSON_EXTRACT(title, '$.en') IS NOT NULL")
                ->get()
            );
        });
    
    Login or Signup to reply.
  2. I work on the same library …

    for this situation I have made a function to fix translatable models.

    not only for result models, but also for nested translatable models loaded with relations.

     protected function fixItemTranslation($item)
        {
            if (!is_object($item) && !is_countable($item)) return;
            if (is_countable($item)) {
                foreach ($item as $sub_item) {
                    $this->fixItemTranslation($sub_item);
                }
                return;
            }
            if (isset($item->translatable)) {
                foreach ($item->translatable as $key => $value) {
                    if ($value == null || $value == "") continue;
                        $t = $item->$value;
                    $item->translatable[$key] = '';
                    $item->{$value} = $t;
                }
            }
            if (property_exists($item, 'relations')) {
                if (count($item->getRelations()) > 0) {
                    $this->fixItemTranslation($item->getRelations());
                }
            }
        }
    

    the main idea is getting the translatable value from translatable object, then remove its key from translatable array, then set it again to ensure desired output.

    I hope it would help.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search