Файли в lang/ перекладають інтерфейс - кнопки, підписи, помилки. Для контенту з бази - назв категорій, описів товарів - потрібен інший підхід, і вибір між трьома.
1. Колонки на кожну мову - найпростіше:
Schema::table('categories', function (Blueprint $table) {
$table->string('name_uk');
$table->string('name_en');
});
Працює, поки мов дві. Кожна нова - міграція й правка всіх запитів.
2. JSON-колонка:
$table->json('name'); // {"uk": "Вакансії", "en": "Jobs"}
protected function casts(): array
{
return ['name' => 'array'];
}
Нова мова не потребує міграції. Мінус - пошук і сортування за перекладом стають незручними, хоча PostgreSQL і MySQL уміють індексувати JSON-шляхи.
3. Окрема таблиця перекладів - рядок на пару «запис + мова». Найгнучкіше: пошук і сортування звичайні, мов скільки завгодно. Ціна - join у кожному запиті.
Що врахувати незалежно від вибору:
- Запасний варіант. Якщо перекладу немає, показувати мову за замовчуванням, а не порожнє місце.
- URL. Мову зазвичай виносять у шлях (
/en/jobs), бо це дає окремі адреси для індексації - на відміну від зберігання вибору лише в сесії. hreflangу розмітці, щоб пошук розумів звʼязок між версіями.- Не лише текст. Формати дат, чисел і валют теж локальні;
Carbon::setLocale()іNumber::format()це враховують.