2.1-2.4: install spatie/laravel-translatable, migrate to JSON, update models & controllers

This commit is contained in:
parsa aghaei 2026-06-23 18:31:51 +03:30
parent 1dc72d8563
commit db7ce880a0
17 changed files with 453 additions and 285 deletions

View File

@ -11,13 +11,13 @@ class AboutMeController extends Controller
{
public function index()
{
$aboutMe = AboutMe::with('skills.translations')->first();
$aboutMe = AboutMe::with('skills')->first();
return response()->json($aboutMe);
}
public function show($id)
{
$aboutMe = AboutMe::with('skills.translations')->findOrFail($id);
$aboutMe = AboutMe::with('skills')->findOrFail($id);
return response()->json($aboutMe);
}
@ -42,24 +42,17 @@ public function destroy($id)
public function getTranslation($id, $locale)
{
$aboutMe = AboutMe::with(['translations' => function ($query) use ($locale) {
$query->where('locale', $locale);
}, 'skills.translations' => function ($query) use ($locale) {
$query->where('locale', $locale);
}])->findOrFail($id);
$aboutMe = AboutMe::with('skills')->findOrFail($id);
if ($aboutMe->translations->isEmpty()) {
if (!$aboutMe->hasTranslation('title', $locale)) {
return response()->json(['message' => 'Translation not found', 'locale' => $locale], 404);
}
$translation = $aboutMe->translations->first();
$skills = $aboutMe->skills->map(function ($skill) use ($locale) {
$translation = $skill->getTranslation($locale);
return [
'id' => $skill->id,
'title' => $translation ? $translation->title : null,
'description' => $translation ? $translation->description : null,
'title' => $skill->getTranslation('title', $locale),
'description' => $skill->getTranslation('description', $locale),
'image' => $skill->image,
'link' => $skill->link,
'percentage' => $skill->percentage,
@ -68,8 +61,8 @@ public function getTranslation($id, $locale)
$data = [
'id' => $aboutMe->id,
'title' => $translation->title,
'description' => $translation->description,
'title' => $aboutMe->getTranslation('title', $locale),
'description' => $aboutMe->getTranslation('description', $locale),
'image' => $aboutMe->image,
'skills' => $skills,
];

View File

@ -14,17 +14,14 @@ public function index($locale): \Illuminate\Http\JsonResponse
{
$perPage = request()->query('per_page', 10);
$projects = Project::with('translations', 'category.translations')->paginate($perPage);
$projects = Project::with('category')->paginate($perPage);
$formattedProjects = $projects->items();
$formattedProjects = array_map(function ($project) use ($locale) {
$translation = $project->translations->firstWhere('locale', $locale);
$categoryTranslation = $project->category->translations->firstWhere('locale', $locale);
return [
'id' => $project->id,
'title' => $translation ? $translation->title : null,
'category' => $categoryTranslation ? $categoryTranslation->title : null,
'title' => $project->getTranslation('title', $locale),
'category' => $project->category?->getTranslation('title', $locale),
'images' => [
['src' => $project->image1, 'position' => '1', 'zIndex' => 1],
['src' => $project->image2, 'position' => '2', 'zIndex' => 2],
@ -44,7 +41,7 @@ public function index($locale): \Illuminate\Http\JsonResponse
'categories' => ProjectCategory::all()->map(function ($category) use ($locale) {
return [
'id' => $category->id,
'title' => $category->translations->firstWhere('locale', $locale)->title ?? null,
'title' => $category->getTranslation('title', $locale),
'image' => $category->image,
];
}),
@ -56,27 +53,22 @@ public function store(StoreProjectRequest $request)
$project = Project::create($request->only(['category_id', 'image1', 'image2']));
foreach (['fa', 'en'] as $locale) {
$project->translations()->create([
'locale' => $locale,
'title' => $request->input("title_$locale"),
'description' => $request->input("description_$locale"),
]);
$project->setTranslation('title', $locale, $request->input("title_$locale"));
$project->setTranslation('description', $locale, $request->input("description_$locale"));
}
$project->save();
return response()->json($project->load('translations'), 201);
return response()->json($project, 201);
}
public function show($id)
public function show($id, $locale)
{
$project = Project::with('translations', 'category.translations')->findOrFail($id);
$translation = $project->translations->firstWhere('locale', 'fa');
$categoryTranslation = $project->category->translations->firstWhere('locale', 'fa');
$project = Project::with('category')->findOrFail($id);
$formattedProject = [
'id' => $project->id,
'title' => $translation ? $translation->title : null,
'category' => $categoryTranslation ? $categoryTranslation->title : null,
'title' => $project->getTranslation('title', $locale),
'category' => $project->category?->getTranslation('title', 'fa'),
'images' => [
['src' => $project->image1, 'position' => '1', 'zIndex' => 1],
['src' => $project->image2, 'position' => '2', 'zIndex' => 2],
@ -94,16 +86,16 @@ public function update(UpdateProjectRequest $request, $id)
$project->update($request->only(['category_id', 'image1', 'image2']));
foreach (['fa', 'en'] as $locale) {
$project->translations()->updateOrCreate(
['locale' => $locale],
[
'title' => $request->input("title_$locale"),
'description' => $request->input("description_$locale"),
]
);
if ($request->has("title_$locale")) {
$project->setTranslation('title', $locale, $request->input("title_$locale"));
}
if ($request->has("description_$locale")) {
$project->setTranslation('description', $locale, $request->input("description_$locale"));
}
}
$project->save();
return response()->json($project->load('translations'));
return response()->json($project);
}
public function destroy($id)

View File

@ -9,19 +9,17 @@ class ServiceController extends Controller
{
public function index($locale)
{
$services = Service::with(['translations' => function ($query) use ($locale) {
$query->where('locale', $locale);
}])->get();
$services = Service::all();
$response = $services->map(function ($service) use ($locale) {
return [
'id' => $service->id,
'imageSrc' => $service->imageSrc,
'altText' => $service->translations->first()->altText ?? '',
'altText' => '',
'created_at' => $service->created_at,
'updated_at' => $service->updated_at,
'title' => optional($service->translations->first())->title,
'description' => optional($service->translations->first())->description,
'title' => $service->getTranslation('title', $locale),
'description' => $service->getTranslation('description', $locale),
];
});
@ -30,13 +28,13 @@ public function index($locale)
public function showTranslation($id, $locale)
{
$service = Service::with('translations')->findOrFail($id);
$service = Service::findOrFail($id);
return response()->json([
'id' => $service->id,
'imageSrc' => $service->imageSrc,
'title' => $service->getTitle($locale),
'description' => $service->getDescription($locale),
'title' => $service->getTranslation('title', $locale),
'description' => $service->getTranslation('description', $locale),
]);
}
}

View File

@ -8,7 +8,7 @@
class Category extends Model
{
use HasFactory;
protected $fillable = [
'name',
'slug',

View File

@ -4,50 +4,16 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class AboutMe extends Model
{
use HasFactory;
use HasFactory, HasTranslations;
protected $table = 'website_about_me';
protected $fillable = ['image'];
/**
* ارتباط با ترجمه‌ها
*/
public function translations()
{
return $this->hasMany(AboutMeTranslation::class, 'about_me_id');
}
/**
* گرفتن ترجمه بر اساس زبان فعلی
*/
public function getTranslation($locale)
{
if ($this->relationLoaded('translations')) {
return $this->translations->firstWhere('locale', $locale);
}
return $this->translations()->where('locale', $locale)->first();
}
/**
* گرفتن عنوان بر اساس زبان فعلی
*/
public function getTitle($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->title : null;
}
/**
* گرفتن توضیحات بر اساس زبان فعلی
*/
public function getDescription($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->description : null;
}
protected array $translatable = ['title', 'description'];
public function skills()
{

View File

@ -1,22 +0,0 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class AboutMeTranslation extends Model
{
use HasFactory;
protected $table = 'website_about_me_translations';
protected $fillable = ['about_me_id', 'locale', 'title', 'description'];
/**
* ارتباط با AboutMe
*/
public function aboutMe()
{
return $this->belongsTo(AboutMe::class, 'about_me_id');
}
}

View File

@ -4,18 +4,16 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class Project extends Model
{
use HasFactory;
use HasFactory, HasTranslations;
protected $table = 'website_projects'; // نام صحیح جدول
protected $table = 'website_projects';
protected $fillable = ['category_id', 'image1', 'image2'];
public function translations()
{
return $this->hasMany(ProjectTranslation::class, 'project_id');
}
protected array $translatable = ['title', 'description'];
public function category()
{

View File

@ -4,16 +4,14 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class ProjectCategory extends Model
{
use HasFactory;
use HasFactory, HasTranslations;
protected $table = 'website_project_categories'; // نام صحیح جدول
protected $table = 'website_project_categories';
protected $fillable = ['image'];
public function translations()
{
return $this->hasMany(ProjectCategoryTranslation::class, 'category_id');
}
protected array $translatable = ['title', 'description'];
}

View File

@ -1,14 +0,0 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ProjectCategoryTranslation extends Model
{
use HasFactory;
protected $table = 'website_project_category_translations'; // نام صحیح جدول
protected $fillable = ['category_id', 'locale', 'title', 'description'];
}

View File

@ -1,19 +0,0 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ProjectTranslation extends Model
{
use HasFactory;
protected $table = 'website_project_translations'; // نام صحیح جدول
protected $fillable = ['project_id', 'locale', 'title', 'description'];
public function project()
{
return $this->belongsTo(Project::class, 'project_id');
}
}

View File

@ -4,48 +4,14 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class Service extends Model
{
use HasFactory;
use HasFactory, HasTranslations;
protected $table = 'website_services'; // نام جدول
protected $fillable = ['imageSrc']; // فیلدهایی که قابل پر کردن هستند
protected $table = 'website_services';
protected $fillable = ['imageSrc'];
/**
* ارتباط با جدول ترجمه‌ها
*/
public function translations()
{
return $this->hasMany(ServiceTranslation::class, 'service_id');
}
/**
* گرفتن ترجمه بر اساس زبان فعلی
*/
public function getTranslation($locale)
{
if ($this->relationLoaded('translations')) {
return $this->translations->firstWhere('locale', $locale);
}
return $this->translations()->where('locale', $locale)->first();
}
/**
* گرفتن عنوان بر اساس زبان فعلی
*/
public function getTitle($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->title : null;
}
/**
* گرفتن توضیحات بر اساس زبان فعلی
*/
public function getDescription($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->description : null;
}
protected array $translatable = ['title', 'description'];
}

View File

@ -1,22 +0,0 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ServiceTranslation extends Model
{
use HasFactory;
protected $table = 'website_service_translations'; // نام جدول
protected $fillable = ['service_id', 'locale', 'title', 'description']; // فیلدهایی که قابل پر کردن هستند
/**
* ارتباط با جدول خدمات
*/
public function service()
{
return $this->belongsTo(Service::class, 'service_id');
}
}

View File

@ -4,56 +4,19 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class Skill extends Model
{
use HasFactory;
use HasFactory, HasTranslations;
protected $table = 'website_skills'; // نام جدول
protected $fillable = ['image', 'link', 'about_me_id', 'percentage']; // فیلدهایی که قابل پر کردن هستند
protected $table = 'website_skills';
protected $fillable = ['image', 'link', 'about_me_id', 'percentage'];
protected array $translatable = ['title', 'description'];
/**
* ارتباط با جدول AboutMe
*/
public function aboutMe()
{
return $this->belongsTo(AboutMe::class, 'about_me_id');
}
/**
* ارتباط با جدول ترجمه‌ها
*/
public function translations()
{
return $this->hasMany(SkillTranslation::class, 'skill_id');
}
/**
* گرفتن ترجمه بر اساس زبان فعلی
*/
public function getTranslation($locale)
{
if ($this->relationLoaded('translations')) {
return $this->translations->firstWhere('locale', $locale);
}
return $this->translations()->where('locale', $locale)->first();
}
/**
* گرفتن عنوان بر اساس زبان فعلی
*/
public function getTitle($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->title : null;
}
/**
* گرفتن توضیحات بر اساس زبان فعلی
*/
public function getDescription($locale)
{
$translation = $this->getTranslation($locale);
return $translation ? $translation->description : null;
}
}

View File

@ -1,22 +0,0 @@
<?php
namespace App\Models\Website;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class SkillTranslation extends Model
{
use HasFactory;
protected $table = 'website_skill_translations'; // نام جدول
protected $fillable = ['skill_id', 'locale', 'title', 'description']; // فیلدهایی که قابل پر کردن هستند
/**
* ارتباط با جدول Skills
*/
public function skill()
{
return $this->belongsTo(Skill::class, 'skill_id');
}
}

View File

@ -8,7 +8,8 @@
"php": "^8.2",
"laravel/framework": "^11.9",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9"
"laravel/tinker": "^2.9",
"spatie/laravel-translatable": "^6.14"
},
"require-dev": {
"fakerphp/faker": "^1.23",

146
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "eba04bbb24b3180d2a6614993a886c4b",
"content-hash": "440d7629e9c875514932936ef5c0c454",
"packages": [
{
"name": "brick/math",
@ -3175,6 +3175,150 @@
],
"time": "2024-04-27T21:32:50+00:00"
},
{
"name": "spatie/laravel-package-tools",
"version": "1.93.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-package-tools.git",
"reference": "d5552849801f2642aea710557463234b59ef65eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/d5552849801f2642aea710557463234b59ef65eb",
"reference": "d5552849801f2642aea710557463234b59ef65eb",
"shasum": ""
},
"require": {
"illuminate/contracts": "^10.0|^11.0|^12.0|^13.0",
"php": "^8.1"
},
"require-dev": {
"mockery/mockery": "^1.5",
"orchestra/testbench": "^8.0|^9.2|^10.0|^11.0",
"pestphp/pest": "^2.1|^3.1|^4.0",
"phpunit/php-code-coverage": "^10.0|^11.0|^12.0",
"phpunit/phpunit": "^10.5|^11.5|^12.5",
"spatie/pest-plugin-test-time": "^2.2|^3.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Spatie\\LaravelPackageTools\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"role": "Developer"
}
],
"description": "Tools for creating Laravel packages",
"homepage": "https://github.com/spatie/laravel-package-tools",
"keywords": [
"laravel-package-tools",
"spatie"
],
"support": {
"issues": "https://github.com/spatie/laravel-package-tools/issues",
"source": "https://github.com/spatie/laravel-package-tools/tree/1.93.1"
},
"funding": [
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2026-05-19T14:06:37+00:00"
},
{
"name": "spatie/laravel-translatable",
"version": "6.14.1",
"source": {
"type": "git",
"url": "https://github.com/spatie/laravel-translatable.git",
"reference": "d120a925cf413b2427f886264bb6eb102ac23d42"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-translatable/zipball/d120a925cf413b2427f886264bb6eb102ac23d42",
"reference": "d120a925cf413b2427f886264bb6eb102ac23d42",
"shasum": ""
},
"require": {
"illuminate/database": "^11.0|^12.0|^13.0",
"illuminate/support": "^11.0|^12.0|^13.0",
"php": "^8.3",
"spatie/laravel-package-tools": "^1.93.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.90",
"mockery/mockery": "^1.6.12",
"orchestra/testbench": "^9.0|^10.0|^11.0",
"pestphp/pest": "^4.0.0"
},
"type": "library",
"extra": {
"aliases": {
"Translatable": "Spatie\\Translatable\\Facades\\Translatable"
},
"laravel": {
"providers": [
"Spatie\\Translatable\\TranslatableServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Spatie\\Translatable\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Freek Van der Herten",
"email": "freek@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
},
{
"name": "Sebastian De Deyne",
"email": "sebastian@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "A trait to make an Eloquent model hold translations",
"homepage": "https://github.com/spatie/laravel-translatable",
"keywords": [
"eloquent",
"i8n",
"laravel-translatable",
"model",
"multilingual",
"spatie",
"translate"
],
"support": {
"issues": "https://github.com/spatie/laravel-translatable/issues",
"source": "https://github.com/spatie/laravel-translatable/tree/6.14.1"
},
"funding": [
{
"url": "https://github.com/spatie",
"type": "github"
}
],
"time": "2026-04-23T08:26:29+00:00"
},
{
"name": "symfony/clock",
"version": "v7.1.1",

View File

@ -0,0 +1,248 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
// === WEBSITE TABLES ===
// website_about_me
Schema::table('website_about_me', function (Blueprint $table) {
$table->json('translations')->nullable()->after('image');
});
$rows = DB::table('website_about_me_translations')->get();
foreach ($rows->groupBy('about_me_id') as $aboutMeId => $translations) {
$data = [];
foreach ($translations as $t) {
$data['title'][$t->locale] = $t->title;
$data['description'][$t->locale] = $t->description;
}
DB::table('website_about_me')->where('id', $aboutMeId)->update(['translations' => json_encode($data)]);
}
Schema::dropIfExists('website_about_me_translations');
// website_skills
Schema::table('website_skills', function (Blueprint $table) {
$table->json('translations')->nullable()->after('percentage');
});
$rows = DB::table('website_skill_translations')->get();
foreach ($rows->groupBy('skill_id') as $skillId => $translations) {
$data = [];
foreach ($translations as $t) {
$data['title'][$t->locale] = $t->title;
$data['description'][$t->locale] = $t->description;
}
DB::table('website_skills')->where('id', $skillId)->update(['translations' => json_encode($data)]);
}
Schema::dropIfExists('website_skill_translations');
// website_services
Schema::table('website_services', function (Blueprint $table) {
$table->json('translations')->nullable()->after('imageSrc');
});
$rows = DB::table('website_service_translations')->get();
foreach ($rows->groupBy('service_id') as $serviceId => $translations) {
$data = [];
foreach ($translations as $t) {
$data['title'][$t->locale] = $t->title;
$data['description'][$t->locale] = $t->description;
}
DB::table('website_services')->where('id', $serviceId)->update(['translations' => json_encode($data)]);
}
Schema::dropIfExists('website_service_translations');
// website_project_categories
Schema::table('website_project_categories', function (Blueprint $table) {
$table->json('translations')->nullable()->after('image');
});
$rows = DB::table('website_project_category_translations')->get();
foreach ($rows->groupBy('category_id') as $categoryId => $translations) {
$data = [];
foreach ($translations as $t) {
$data['title'][$t->locale] = $t->title;
$data['description'][$t->locale] = $t->description;
}
DB::table('website_project_categories')->where('id', $categoryId)->update(['translations' => json_encode($data)]);
}
Schema::dropIfExists('website_project_category_translations');
// website_projects
Schema::table('website_projects', function (Blueprint $table) {
$table->json('translations')->nullable()->after('image2');
});
$rows = DB::table('website_project_translations')->get();
foreach ($rows->groupBy('project_id') as $projectId => $translations) {
$data = [];
foreach ($translations as $t) {
$data['title'][$t->locale] = $t->title;
$data['description'][$t->locale] = $t->description;
}
DB::table('website_projects')->where('id', $projectId)->update(['translations' => json_encode($data)]);
}
Schema::dropIfExists('website_project_translations');
// === BLOG TABLES ===
Schema::table('posts', function (Blueprint $table) {
$table->json('translations')->nullable()->after('featured_image');
});
Schema::table('categories', function (Blueprint $table) {
$table->json('translations')->nullable()->after('image');
});
Schema::table('tags', function (Blueprint $table) {
$table->json('translations')->nullable()->after('slug');
});
}
public function down(): void
{
// Restore website_about_me_translations
Schema::create('website_about_me_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('about_me_id');
$table->string('locale')->index();
$table->string('title');
$table->text('description');
$table->timestamps();
$table->foreign('about_me_id')->references('id')->on('website_about_me')->onDelete('cascade');
$table->unique(['about_me_id', 'locale']);
});
DB::table('website_about_me')->whereNotNull('translations')->each(function ($row) {
$translations = json_decode($row->translations, true);
if (!$translations) return;
foreach (($translations['title'] ?? []) as $locale => $title) {
DB::table('website_about_me_translations')->insert([
'about_me_id' => $row->id,
'locale' => $locale,
'title' => $title,
'description' => $translations['description'][$locale] ?? '',
]);
}
});
Schema::table('website_about_me', function (Blueprint $table) {
$table->dropColumn('translations');
});
// Restore website_skill_translations
Schema::create('website_skill_translations', function (Blueprint $table) {
$table->id();
$table->foreignId('skill_id')->constrained('website_skills')->onDelete('cascade');
$table->string('locale')->index();
$table->string('title');
$table->text('description');
$table->unique(['skill_id', 'locale']);
$table->timestamps();
});
DB::table('website_skills')->whereNotNull('translations')->each(function ($row) {
$translations = json_decode($row->translations, true);
if (!$translations) return;
foreach (($translations['title'] ?? []) as $locale => $title) {
DB::table('website_skill_translations')->insert([
'skill_id' => $row->id,
'locale' => $locale,
'title' => $title,
'description' => $translations['description'][$locale] ?? '',
]);
}
});
Schema::table('website_skills', function (Blueprint $table) {
$table->dropColumn('translations');
});
// Restore website_service_translations
Schema::create('website_service_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('service_id');
$table->string('locale')->index();
$table->string('title');
$table->text('description');
$table->timestamps();
$table->foreign('service_id')->references('id')->on('website_services')->onDelete('cascade');
$table->unique(['service_id', 'locale']);
});
DB::table('website_services')->whereNotNull('translations')->each(function ($row) {
$translations = json_decode($row->translations, true);
if (!$translations) return;
foreach (($translations['title'] ?? []) as $locale => $title) {
DB::table('website_service_translations')->insert([
'service_id' => $row->id,
'locale' => $locale,
'title' => $title,
'description' => $translations['description'][$locale] ?? '',
]);
}
});
Schema::table('website_services', function (Blueprint $table) {
$table->dropColumn('translations');
});
// Restore website_project_category_translations
Schema::create('website_project_category_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('category_id');
$table->string('locale')->index();
$table->string('title');
$table->text('description');
$table->timestamps();
$table->foreign('category_id')->references('id')->on('website_project_categories')->onDelete('cascade');
$table->unique(['category_id', 'locale']);
});
DB::table('website_project_categories')->whereNotNull('translations')->each(function ($row) {
$translations = json_decode($row->translations, true);
if (!$translations) return;
foreach (($translations['title'] ?? []) as $locale => $title) {
DB::table('website_project_category_translations')->insert([
'category_id' => $row->id,
'locale' => $locale,
'title' => $title,
'description' => $translations['description'][$locale] ?? '',
]);
}
});
Schema::table('website_project_categories', function (Blueprint $table) {
$table->dropColumn('translations');
});
// Restore website_project_translations
Schema::create('website_project_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('project_id');
$table->string('locale')->index();
$table->string('title');
$table->text('description');
$table->timestamps();
$table->foreign('project_id')->references('id')->on('website_projects')->onDelete('cascade');
$table->unique(['project_id', 'locale']);
});
DB::table('website_projects')->whereNotNull('translations')->each(function ($row) {
$translations = json_decode($row->translations, true);
if (!$translations) return;
foreach (($translations['title'] ?? []) as $locale => $title) {
DB::table('website_project_translations')->insert([
'project_id' => $row->id,
'locale' => $locale,
'title' => $title,
'description' => $translations['description'][$locale] ?? '',
]);
}
});
Schema::table('website_projects', function (Blueprint $table) {
$table->dropColumn('translations');
});
// Blog tables
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('translations');
});
Schema::table('categories', function (Blueprint $table) {
$table->dropColumn('translations');
});
Schema::table('tags', function (Blueprint $table) {
$table->dropColumn('translations');
});
}
};