{"id":593,"date":"2025-09-01T12:22:16","date_gmt":"2025-09-01T12:22:16","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=593"},"modified":"2025-09-02T11:05:55","modified_gmt":"2025-09-02T11:05:55","slug":"building-multi-language-seo-friendly-sites-in-laravel","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/building-multi-language-seo-friendly-sites-in-laravel\/","title":{"rendered":"Building Multi-Language SEO-Friendly Sites in Laravel"},"content":{"rendered":"\n<p>Expanding your Laravel application to support multiple languages can dramatically improve reach and SEO. By building SEO-friendly URLs, localized metadata, and hreflang tags, you help search engines index your content correctly across regions. In this guide, we\u2019ll set up localization in Laravel, implement multi-language slugs, add localized SEO tags, update the sitemap, and build a UI language switcher.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Setting Up Laravel Localization<\/strong><\/h2>\n\n\n\n<p>Laravel provides built-in localization support. Start by creating language files in <code>resources\/lang\/<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">resources\/lang\/en\/messages.php\nresources\/lang\/tr\/messages.php<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ resources\/lang\/en\/messages.php<\/span>\n<span class=\"hljs-keyword\">return<\/span> &#91;\n    <span class=\"hljs-string\">'welcome'<\/span> =&gt; <span class=\"hljs-string\">'Welcome to our site!'<\/span>,\n];\n\n<span class=\"hljs-comment\">\/\/ resources\/lang\/tr\/messages.php<\/span>\n<span class=\"hljs-keyword\">return<\/span> &#91;\n    <span class=\"hljs-string\">'welcome'<\/span> =&gt; <span class=\"hljs-string\">'Sitemize ho\u015f geldiniz!'<\/span>,\n];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You can now use <code>{{ __('messages.welcome') }}<\/code> in Blade templates, and it will load the text based on the selected locale.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Language-Based Routes and Slugs<\/strong><\/h2>\n\n\n\n<p>SEO-friendly multi-language sites should use localized URLs like <code>\/en\/blog<\/code> and <code>\/tr\/blog<\/code>. You can group routes by locale:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ routes\/web.php<\/span>\nRoute::group(&#91;<span class=\"hljs-string\">'prefix'<\/span> =&gt; <span class=\"hljs-string\">'{locale}'<\/span>, <span class=\"hljs-string\">'middleware'<\/span> =&gt; <span class=\"hljs-string\">'setlocale'<\/span>], <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">()<\/span> <\/span>{\n    Route::get(<span class=\"hljs-string\">'\/blog'<\/span>, &#91;BlogController::class, <span class=\"hljs-string\">'index'<\/span>]);\n    Route::get(<span class=\"hljs-string\">'\/blog\/{slug}'<\/span>, &#91;BlogController::class, <span class=\"hljs-string\">'show'<\/span>]);\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Create a <code>setlocale<\/code> middleware to change the app locale from the route parameter:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ app\/Http\/Middleware\/SetLocale.php<\/span>\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">App<\/span>\\<span class=\"hljs-title\">Http<\/span>\\<span class=\"hljs-title\">Middleware<\/span>;\n\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Closure<\/span>;\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Illuminate<\/span>\\<span class=\"hljs-title\">Support<\/span>\\<span class=\"hljs-title\">Facades<\/span>\\<span class=\"hljs-title\">App<\/span>;\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SetLocale<\/span>\n<\/span>{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">handle<\/span><span class=\"hljs-params\">($request, Closure $next)<\/span>\n    <\/span>{\n        $locale = $request-&gt;route(<span class=\"hljs-string\">'locale'<\/span>, <span class=\"hljs-string\">'en'<\/span>);\n        App::setLocale($locale);\n\n        <span class=\"hljs-keyword\">return<\/span> $next($request);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This ensures the correct language is applied based on the URL prefix.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Localized SEO Tags and hreflang<\/strong><\/h2>\n\n\n\n<p>Each language should have its own SEO metadata. In Blade, dynamically output <code>&lt;title&gt;<\/code>, meta descriptions, and hreflang tags:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;title&gt;{{ $post-&gt;getTranslation(<span class=\"hljs-string\">'title'<\/span>, app()-&gt;getLocale()) }}&lt;\/title&gt;\n&lt;meta name=<span class=\"hljs-string\">\"description\"<\/span> content=<span class=\"hljs-string\">\"{{ $post-&gt;getTranslation('meta_description', app()-&gt;getLocale()) }}\"<\/span>&gt;\n\n&lt;!-- Hreflang <span class=\"hljs-keyword\">for<\/span> Google --&gt;\n&lt;link rel=<span class=\"hljs-string\">\"alternate\"<\/span> hreflang=<span class=\"hljs-string\">\"en\"<\/span> href=<span class=\"hljs-string\">\"{{ url('en\/blog\/'.$post-&gt;slug_en) }}\"<\/span> \/&gt;\n&lt;link rel=<span class=\"hljs-string\">\"alternate\"<\/span> hreflang=<span class=\"hljs-string\">\"tr\"<\/span> href=<span class=\"hljs-string\">\"{{ url('tr\/blog\/'.$post-&gt;slug_tr) }}\"<\/span> \/&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>hreflang<\/code> attributes signal to Google which page corresponds to each language, preventing duplicate content issues.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>UI Example: Language Switcher<\/strong><\/h2>\n\n\n\n<p>Add a language switcher so users can easily change between languages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;nav&gt;\n  &lt;ul&gt;\n    &lt;li&gt;&lt;a href=<span class=\"hljs-string\">\"\/en{{ request()-&gt;getPathInfo() }}\"<\/span>&gt;English&lt;\/a&gt;&lt;\/li&gt;\n    &lt;li&gt;&lt;a href=<span class=\"hljs-string\">\"\/tr{{ request()-&gt;getPathInfo() }}\"<\/span>&gt;T\u00fcrk\u00e7e&lt;\/a&gt;&lt;\/li&gt;\n  &lt;\/ul&gt;\n&lt;\/nav&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This keeps the same path while switching the language prefix. For example, <code>\/en\/blog<\/code> \u2192 <code>\/tr\/blog<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Multi-Language Sitemaps<\/strong><\/h2>\n\n\n\n<p>Update your <code>sitemap.xml<\/code> to include entries for each language version of a page. Example for a blog post:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">url<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">loc<\/span>&gt;<\/span>https:\/\/example.com\/en\/blog\/my-post<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">loc<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">xhtml:link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"alternate\"<\/span> <span class=\"hljs-attr\">hreflang<\/span>=<span class=\"hljs-string\">\"tr\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"https:\/\/example.com\/tr\/blog\/my-post\"<\/span>\/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">lastmod<\/span>&gt;<\/span>2025-09-01<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">lastmod<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">url<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This helps Google index all language variations while avoiding duplicate content penalties.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Single-Language vs Multi-Language SEO<\/strong><\/h2>\n\n\n\n<table class=\"wp-block-table\"><tbody>\n<tr>\n<td><strong>Feature<\/strong><\/td>\n<td><strong>Single-Language<\/strong><\/td>\n<td><strong>Multi-Language<\/strong><\/td>\n<\/tr>\n<tr>\n<td><strong>Reach<\/strong><\/td>\n<td>Only local audience<\/td>\n<td>Global audience<\/td>\n<\/tr>\n<tr>\n<td><strong>SEO<\/strong><\/td>\n<td>One set of indexed pages<\/td>\n<td>Each language indexed separately<\/td>\n<\/tr>\n<tr>\n<td><strong>Complexity<\/strong><\/td>\n<td>Simple setup<\/td>\n<td>Requires localization &amp; hreflang<\/td>\n<\/tr>\n<tr>\n<td><strong>User Experience<\/strong><\/td>\n<td>One language for all<\/td>\n<td>Visitors can read in their language<\/td>\n<\/tr>\n<tr>\n<td><strong>Sitemaps<\/strong><\/td>\n<td>One sitemap file<\/td>\n<td>Multiple language entries<\/td>\n<\/tr>\n<\/tbody><\/table>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wrapping Up<\/strong><\/h2>\n\n\n\n<p>Building a multi-language SEO-friendly site in Laravel involves localized routes, translated content, SEO metadata, hreflang attributes, and updated sitemaps. By adding a language switcher UI, you improve user experience while boosting search visibility worldwide. Compared to single-language sites, multi-language setups open the door to new markets and higher organic traffic.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What\u2019s Next<\/strong><\/h2>\n\n\n\n<p>Continue enhancing your Laravel SEO stack with these guides:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/blog\/laravel-seo-guide-optimizing-meta-slugs-and-sitemaps\">Laravel SEO Guide: Optimizing Meta, Slugs, and Sitemaps<\/a><\/li>\n<li><a href=\"\/blog\/how-to-build-an-xml-sitemap-generator-in-laravel\">How to Build an XML Sitemap Generator in Laravel<\/a><\/li>\n<li><a href=\"\/blog\/creating-json-ld-structured-data-in-laravel-for-seo\">Creating JSON-LD Structured Data in Laravel for SEO<\/a><\/li>\n<\/ul>\n\n","protected":false},"excerpt":{"rendered":"<p>Expanding your Laravel application to support multiple languages can dramatically improve reach and SEO. By building SEO-friendly URLs, localized metadata, and hreflang tags, you help search engines index your content correctly across regions. In this guide, we\u2019ll set up localization in Laravel, implement multi-language slugs, add localized SEO tags, update the sitemap, and build a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":597,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[133,94,134,109,117],"class_list":["post-593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-hreflang","tag-localization","tag-multi-language","tag-seo","tag-sitemap"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/593","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/comments?post=593"}],"version-history":[{"count":2,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/593\/revisions"}],"predecessor-version":[{"id":604,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/593\/revisions\/604"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/597"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}