@php /* ── Temel değişkenler ─────────────────────────────────────── */ $siteName = settings('branding.site_name'); $siteUrl = rtrim(url('/'), '/'); /* i18n B20 (Day 29) — locale-aware SEO copy. İSİM = içerik (çevrilmez); * ŞABLON/SUFFIX = UI metni (çevrilir). $L aktif locale stringini seçer * (AR/ES/RU henüz yoksa EN'e düşer). TR çıktı byte-identical kalır. */ $locale = app()->getLocale() ?: 'tr'; $L = function (string $tr, string $en, ?string $ar = null, ?string $es = null, ?string $ru = null) use ($locale) { return match ($locale) { 'en' => $en, 'ar' => $ar ?? $en, 'es' => $es ?? $en, 'ru' => $ru ?? $en, default => $tr, }; }; $ogLocaleMap = ['tr' => 'tr_TR', 'en' => 'en_US', 'ar' => 'ar_AR', 'es' => 'es_ES', 'ru' => 'ru_RU']; $ogLocale = $ogLocaleMap[$locale] ?? 'tr_TR'; /* Tür adını aktif locale'e çevir (guarded — genre_translations yoksa TR'ye * düşer, 500 yok). Görünür title'da geçmez ama keywords/JSON-LD genre için. */ $trGenre = function ($name) use ($locale) { $name = trim((string) $name); if ($name === '' || $locale === 'tr') return $name; try { $t = \Illuminate\Support\Facades\DB::table('genre_translations as gt') ->join('genres as g', 'g.id', '=', 'gt.genre_id') ->where('gt.locale', $locale) ->whereRaw('LOWER(g.name) = ?', [mb_strtolower($name, 'UTF-8')]) ->value('gt.name'); return $t ?: $name; } catch (\Throwable $e) { return $name; } }; /* Yönetmen ve oyuncular */ /* R13: kişi adlarını SEO çıktısında Latin alfabesinde göster * (film adı dokunulmaz, sadece oyuncu/yönetmen isimleri). */ $directorName = (isset($credits['directing']) && $credits['directing']->isNotEmpty()) ? latinizeName($credits['directing']->first()->name) : null; $topCastArr = (isset($credits['actors']) && $credits['actors']->isNotEmpty()) ? $credits['actors']->take(4)->map(fn($a) => latinizeName($a->name))->toArray() : []; $topCastStr = implode(', ', array_slice($topCastArr, 0, 3)); /* IMDb puanı (1 ondalık) */ $imdbStr = $title->rating ? 'IMDb ' . number_format((float)$title->rating, 1) . '/10' : null; /* Orijinal başlık — META TITLE / DESC / KEYWORDS hepsinde gerekiyor, erken tanımla */ $origTitle = ($title->original_title && $title->original_title !== $title->name) ? $title->original_title : null; /* Kelime sınırında kesen yardımcı (title için) */ $wordCut = function(string $s, int $max): string { if (mb_strlen($s, 'UTF-8') <= $max) return $s; $sub = mb_substr($s, 0, $max, 'UTF-8'); $pos = mb_strrpos($sub, ' ', 0, 'UTF-8'); if ($pos !== false && $pos >= intval($max * 0.55)) { $sub = mb_substr($sub, 0, $pos, 'UTF-8'); } return rtrim($sub, '.,;:!?- ') . '…'; }; /* Cümle/kelime sınırında kesen yardımcı (description için) */ $descLimit = function(string $text, int $max = 155): string { $len = mb_strlen($text, 'UTF-8'); if ($len <= $max) return $text; // 250 karaktere kadar cümle sonu ara (. ! ?) — böylece 155'i geçen cümleler de tam biter $window = mb_substr($text, 0, min(250, $len), 'UTF-8'); $sentPos = -1; foreach (['. ', '! ', '? ', ".\n", "!\n", "?\n"] as $p) { $found = mb_strrpos($window, $p, 0, 'UTF-8'); if ($found !== false && $found >= intval($max * 0.4)) { $sentPos = max($sentPos, (int)$found); } } // Metin nokta/ünlem/soru ile bitiyorsa (boşluk yok sonunda) da yakala $lastChar = mb_substr($window, -1, 1, 'UTF-8'); if ($sentPos === -1 && in_array($lastChar, ['.', '!', '?']) && mb_strlen($window, 'UTF-8') >= intval($max * 0.4)) { return $window; } if ($sentPos !== -1) { return mb_substr($window, 0, $sentPos + 1, 'UTF-8'); } // Cümle bulunamadı — 155 içinde kelime sınırında kes $sub = mb_substr($text, 0, $max, 'UTF-8'); $pos = mb_strrpos($sub, ' ', 0, 'UTF-8'); if ($pos !== false && $pos >= intval($max * 0.4)) { return rtrim(mb_substr($sub, 0, $pos, 'UTF-8'), '.,;:!?-') . '…'; } return rtrim($sub, '.,;:!?- ') . '…'; }; /* ── META TITLE ───────────────────────────────────────────── * Admin'de seo_title tanımlıysa onu kullan, yoksa otomatik oluştur. * ──────────────────────────────────────────────────────────────────── */ $customSeoTitle = trim((string) ($title->seo_title ?? '')); if ($customSeoTitle !== '') { $ogTitle = $customSeoTitle; } elseif ($title->is_series) { $ogTitle = $title->name . $L( " - Tüm Sezonlar, Konusu ve Nerede İzlenir | {$siteName}", " - All Seasons, Plot & Where to Watch | {$siteName}", " - جميع المواسم والقصة وأين تشاهد | {$siteName}", " - Todas las Temporadas, Trama y Dónde Ver | {$siteName}", " - Все сезоны, сюжет и где смотреть | {$siteName}", ); } else { $yearDisp = $title->year ? " ({$title->year})" : ''; $ogTitle = "{$title->name}{$yearDisp}" . $L( " - Konusu, Oyuncuları, Nerede İzlenir | {$siteName}", " - Plot, Cast & Where to Watch | {$siteName}", " - القصة والممثلون وأين تشاهد | {$siteName}", " - Trama, Reparto y Dónde Ver | {$siteName}", " - Сюжет, актёры и где смотреть | {$siteName}", ); } /* ── META DESCRIPTION ──────────────────────────────────────── */ /* Hierarchy: admin seo_description > AI ozet_tr (Day 12-15 enrichment) * > DB title->description > structured fallback. AI ozet is spoiler-safe * Turkish copy and beats raw TMDB ham translation in most cases. */ $customSeoDesc = trim((string) ($title->seo_description ?? '')); if ($customSeoDesc !== '') { $metaDesc = $descLimit($customSeoDesc); $rawDesc = $customSeoDesc; } else { try { $aiOzetTr = trim(strip_tags((string) ($title->aiContent->ozet_tr ?? ''))); } catch (\Throwable $e) { $aiOzetTr = ''; } $rawDesc = $aiOzetTr !== '' ? $aiOzetTr : trim(strip_tags((string) $title->description)); } if ($customSeoDesc !== '') { // zaten set edildi yukarıda } elseif ($rawDesc !== '') { /* Düzeltme 8: Diziler için "tüm bölümler/sezon detayları" ek cümlesi */ if ($title->is_series) { /* R27: dizi kapanışı "sezon ve bölüm rehberi" formatında */ $rawDesc = rtrim($rawDesc, ' .') . $L( ". Sezon ve bölüm rehberi: tüm bölümler, yayın tarihleri ve oyuncu kadrosu {$siteName}'de.", ". Season and episode guide: all episodes, air dates and cast on {$siteName}.", ". دليل المواسم والحلقات: جميع الحلقات وتواريخ العرض والممثلون على {$siteName}.", ". Guía de temporadas y episodios: todos los episodios, fechas de emisión y reparto en {$siteName}.", ". Гид по сезонам и сериям: все серии, даты выхода и актёры на {$siteName}.", ); } /* Uzun DB açıklamasını 155'e kıs */ $metaDesc = $descLimit($rawDesc); } elseif ($title->is_series) { /* Yapılandırılmış dizi açıklaması — Düzeltme 8: kapanış cümlesi * "tüm bölümler/sezon detayları" formatına alındı */ $parts = ["{$title->name}"]; if ($origTitle && $origTitle !== $title->name) $parts[] = "({$origTitle})"; if ($title->seasons_count) $parts[] = $L("{$title->seasons_count} sezon", "{$title->seasons_count} seasons", "{$title->seasons_count} مواسم", "{$title->seasons_count} temporadas", "{$title->seasons_count} сезонов"); if ($topCastStr) $parts[] = $L("Oyuncular: {$topCastStr}", "Cast: {$topCastStr}", "الممثلون: {$topCastStr}", "Reparto: {$topCastStr}", "Актёры: {$topCastStr}"); if ($imdbStr) $parts[] = $imdbStr; $fallback = implode(', ', $parts) . $L( ". Sezon ve bölüm rehberi: tüm bölümler, yayın tarihleri ve oyuncu kadrosu {$siteName}'de.", ". Season and episode guide: all episodes, air dates and cast on {$siteName}.", ". دليل المواسم والحلقات: جميع الحلقات وتواريخ العرض والممثلون على {$siteName}.", ". Guía de temporadas y episodios: todos los episodios, fechas de emisión y reparto en {$siteName}.", ". Гид по сезонам и сериям: все серии, даты выхода и актёры на {$siteName}.", ); $metaDesc = $descLimit($fallback); } else { /* Yapılandırılmış film açıklaması — "nerede izlenir" odaklı */ $dispOrig = ($origTitle && $origTitle !== $title->name) ? " ({$origTitle})" : ''; $fallback = $L( "{$title->name}{$dispOrig} filmi hakkında tüm detaylar: konusu, oyuncuları" . ($imdbStr ? ", {$imdbStr}" : '') . ($directorName ? ", yönetmen {$directorName}" : '') . ". Netflix, BluTV ve diğer platformlarda nerede izleneceğini {$siteName}'de öğren.", "Everything about {$title->name}{$dispOrig}: plot, cast" . ($imdbStr ? ", {$imdbStr}" : '') . ($directorName ? ", directed by {$directorName}" : '') . ". Find where to watch on Netflix, BluTV and more at {$siteName}.", "كل ما يخص {$title->name}{$dispOrig}: القصة والممثلون" . ($imdbStr ? "، {$imdbStr}" : '') . ($directorName ? "، إخراج {$directorName}" : '') . ". اعرف أين تشاهده على {$siteName}.", "Todo sobre {$title->name}{$dispOrig}: trama, reparto" . ($imdbStr ? ", {$imdbStr}" : '') . ($directorName ? ", dirigida por {$directorName}" : '') . ". Descubre dónde verla en {$siteName}.", "Всё о {$title->name}{$dispOrig}: сюжет, актёры" . ($imdbStr ? ", {$imdbStr}" : '') . ($directorName ? ", режиссёр {$directorName}" : '') . ". Узнайте, где смотреть, на {$siteName}.", ); $metaDesc = $descLimit($fallback); } /* ── META KEYWORDS ─────────────────────────────────────────── */ $pageUrl = urls()->title($title); $kwBase = collect($title->keywords ?? []) ->map(fn($k) => trim((string)($k->display_name ?: $k->name)))->filter()->take(5)->values(); $kwGenre = collect($title->genres ?? []) ->map(fn($g) => $trGenre(trim((string)($g->display_name ?? $g->name))))->filter()->take(3)->values(); if ($title->is_series) { $kwExtra = array_filter([ $title->name, $L("{$title->name} izle", "watch {$title->name}"), $L("{$title->name} konusu", "{$title->name} plot"), $L("{$title->name} oyuncuları", "{$title->name} cast"), $title->seasons_count ? $L("{$title->name} {$title->seasons_count}. sezon", "{$title->name} season {$title->seasons_count}") : null, $L("{$title->name} nerede izlenir", "where to watch {$title->name}"), $L("{$title->name} hangi platformda", "{$title->name} streaming"), $L("{$title->name} türkçe altyazılı", "{$title->name} subtitles"), $origTitle ? $origTitle : null, $directorName ? $L("{$directorName} dizisi", "{$directorName} tv series") : null, $L('dizi izle', 'watch tv series'), $L('türk dizileri', 'turkish series'), $title->year ? $L("{$title->year} dizileri", "{$title->year} tv shows") : null, ]); } else { $kwExtra = array_filter([ $title->name, $L("{$title->name} izle", "watch {$title->name}"), $L("{$title->name} konusu", "{$title->name} plot"), $L("{$title->name} oyuncuları", "{$title->name} cast"), $L("{$title->name} nerede izlenir", "where to watch {$title->name}"), $L("{$title->name} türkçe dublaj", "{$title->name} dubbed"), $L("{$title->name} full hd izle", "watch {$title->name} hd"), $L("{$title->name} fragman", "{$title->name} trailer"), $origTitle ? $origTitle : null, $directorName ? $L("{$directorName} filmi", "{$directorName} movie") : null, $L('film izle', 'watch movies'), $L('türkçe dublaj', 'where to watch'), $title->year ? $L("{$title->year} filmleri", "{$title->year} movies") : null, ]); } $metaKeywords = $kwBase->concat($kwGenre) ->concat($kwExtra) ->filter()->unique()->take(18)->join(', '); /* ── GÖRSELLER ─────────────────────────────────────────────── */ $ogImage = $title->backdrop ? urls()->image($title->backdrop) : ($title->poster ? urls()->image($title->poster) : null); $ogImgW = $title->backdrop ? 1280 : 300; $ogImgH = $title->backdrop ? 720 : 450; $defaultOgImg = url('og/cine5-og.jpg'); $ogImageFinal = $ogImage ?? $defaultOgImg; $ogImgWFinal = $ogImage ? $ogImgW : 1200;
When tragedy strikes his remarkable robot and the beautiful girl next door, lonely teenage genius Paul tries to save them by pushing technology beyond its known limits into a terrifying new realm.