{{-- OG locale mapping --}}
@php
$ogLocaleMap = [
'fr' => 'fr_FR', 'en' => 'en_US', 'it' => 'it_IT', 'ar' => 'ar_SA',
'de' => 'de_DE', 'es' => 'es_ES', 'pt' => 'pt_BR', 'ru' => 'ru_RU',
];
@endphp
{{-- Hreflang tags --}}
@if(!empty($localeUrls))
@php
$pageSuffix = (!empty($currentPage) && $currentPage > 1) ? '/' . $currentPage : '';
@endphp
@foreach($localeUrls as $code => $path)
@endforeach
@endif
{{-- Canonical URL --}}
@php
$canonicalUrl = url()->current();
@endphp
{{-- Rel prev/next for split posts --}}
@if(!empty($totalPages) && $totalPages > 1)
@php
$baseUrl = (!empty($post) && !empty($locale))
? route('content.show', ['locale' => $locale, 'slug' => $post->translation($locale)?->slug])
: url()->current();
@endphp
@if($currentPage > 1)
@endif
@if($currentPage < $totalPages)
@endif
@endif
{{-- Open Graph meta tags --}}
@php
$ogTitle = '';
$ogDescription = '';
$ogImage = '';
$ogType = 'website';
$ogLocale = $locale ?? 'fr';
$ogLocaleFormatted = $ogLocaleMap[$ogLocale] ?? $ogLocale;
if (!empty($post)) {
$ogTrans = $post->translation($ogLocale);
$ogTitle = $ogTrans?->meta_title ?: $ogTrans?->title ?: '';
$ogDescription = $ogTrans?->meta_description ?: Str::limit(strip_tags($ogTrans?->body ?? ''), 200);
// Enrich for subpages
if (!empty($currentPage) && $currentPage > 1 && !empty($totalPages) && !empty($globalToc[$currentPage - 1]['title'])) {
$chapterTitle = $globalToc[$currentPage - 1]['title'];
$ogTitle = $ogTitle . ' - ' . $chapterTitle . ' (' . $currentPage . '/' . $totalPages . ')';
$ogDescription = Str::limit(strip_tags($pageBody ?? ''), 200);
}
$ogImage = $ogTrans?->og_image ?? '';
$ogType = $post->isPage() ? 'website' : 'article';
} elseif (!empty($category)) {
$catTrans = $category->translation($ogLocale);
$ogTitle = $catTrans?->name ?? '';
$ogDescription = $catTrans?->description ?? '';
}
if (empty($ogTitle)) {
$ogTitle = config('app.name', 'Pierre2.net');
}
@endphp
@if($ogDescription)
@endif
@if($ogImage)
@endif
@if(!empty($localeUrls))
@foreach($localeUrls as $code => $path)
@if($code !== $ogLocale)
@endif
@endforeach
@endif
{{-- Twitter Card meta tags --}}
@if($ogDescription)
@endif
@if($ogImage)
@endif
{{-- Article timestamps --}}
@if(!empty($post) && !$post->isPage())
@if($post->updated_at)
@endif
@endif
{{-- JSON-LD Structured Data --}}
@php
$siteName = 'Pierre2.net';
$siteUrl = rtrim(config('app.url'), '/');
$jsonLdScripts = [];
// WebSite schema (all pages)
$webSiteSchema = [
'@context' => 'https://schema.org',
'@type' => 'WebSite',
'name' => $siteName,
'url' => $siteUrl,
];
$webSiteSchema['potentialAction'] = [
[
'@type' => 'SearchAction',
'target' => [
'@type' => 'EntryPoint',
'urlTemplate' => $siteUrl . '/' . $ogLocale . '/search?q={search_term_string}',
],
'query-input' => [
'@type' => 'PropertyValueSpecification',
'valueRequired' => true,
'valueName' => 'search_term_string',
],
],
];
$jsonLdScripts[] = $webSiteSchema;
// WebPage schema (all pages)
$webPageSchema = [
'@context' => 'https://schema.org',
'@type' => 'WebPage',
'name' => $ogTitle,
'url' => $canonicalUrl,
'inLanguage' => $ogLocale,
];
if ($ogDescription) {
$webPageSchema['description'] = $ogDescription;
}
$jsonLdScripts[] = $webPageSchema;
// Article + Person + BreadcrumbList for posts
if (!empty($post) && !$post->isPage()) {
$articleTrans = $post->translation($ogLocale);
$articleSchema = [
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => $articleTrans?->title ?? $ogTitle,
'url' => $canonicalUrl,
'inLanguage' => $ogLocale,
];
if ($post->published_at) {
$articleSchema['datePublished'] = $post->published_at->toIso8601String();
} elseif ($post->created_at) {
$articleSchema['datePublished'] = $post->created_at->toIso8601String();
}
if ($post->updated_at) {
$articleSchema['dateModified'] = $post->updated_at->toIso8601String();
}
if ($ogImage) {
$articleSchema['image'] = Str::startsWith($ogImage, 'http') ? $ogImage : asset('storage/' . $ogImage);
}
// Author
$author = $post->author;
if ($author) {
$personSchema = [
'@type' => 'Person',
'name' => $author->name,
];
$articleSchema['author'] = $personSchema;
}
// Word count
$wordCount = str_word_count(strip_tags($articleTrans?->body ?? ''));
if ($wordCount > 0) {
$articleSchema['wordCount'] = $wordCount;
}
// Article section (category)
if ($post->relationLoaded('categories') && $post->categories->isNotEmpty()) {
$catName = $post->categories->first()->translation($ogLocale)?->name;
if ($catName) {
$articleSchema['articleSection'] = $catName;
}
}
// Keywords from tags
if ($post->relationLoaded('tags') && $post->tags->isNotEmpty()) {
$keywords = $post->tags
->map(fn ($tag) => $tag->translation($ogLocale)?->name)
->filter()
->values()
->all();
if ($keywords) {
$articleSchema['keywords'] = implode(', ', $keywords);
}
}
$jsonLdScripts[] = $articleSchema;
// BreadcrumbList
$breadcrumbItems = [
[
'@type' => 'ListItem',
'position' => 1,
'name' => $siteName,
'item' => $siteUrl . '/' . $ogLocale,
],
];
// Add category if available
if ($post->relationLoaded('categories') && $post->categories->isNotEmpty()) {
$firstCat = $post->categories->first();
$catTranslation = $firstCat->translation($ogLocale);
if ($catTranslation && $catTranslation->slug) {
$breadcrumbItems[] = [
'@type' => 'ListItem',
'position' => 2,
'name' => $catTranslation->name,
'item' => $siteUrl . '/' . $ogLocale . '/category/' . $catTranslation->slug,
];
}
}
$breadcrumbItems[] = [
'@type' => 'ListItem',
'position' => count($breadcrumbItems) + 1,
'name' => $articleTrans?->title ?? $ogTitle,
];
$jsonLdScripts[] = [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $breadcrumbItems,
];
}
// BreadcrumbList for category pages
if (!empty($category)) {
$catTransBc = $category->translation($ogLocale);
$jsonLdScripts[] = [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => [
[
'@type' => 'ListItem',
'position' => 1,
'name' => $siteName,
'item' => $siteUrl . '/' . $ogLocale,
],
[
'@type' => 'ListItem',
'position' => 2,
'name' => $catTransBc?->name ?? '',
],
],
];
}
@endphp
@foreach($jsonLdScripts as $schema)
@endforeach