Regional Subdomains Setup (ru.site.com, en.site.com)
Regional subdomains — one way to organize a multilingual or multi-regional site. Each region gets separate subdomain: ru.site.com, en.site.com, de.site.com. Search engines treat them as separate sites or closely related resources with hreflang attributes.
DNS Setup
; Each subdomain points to needed server or load balancer
ru.example.com. IN A 185.10.1.1 ; server in Russia
en.example.com. IN A 52.18.2.2 ; server in EU
de.example.com. IN A 52.18.2.2 ; same EU server
www.example.com. IN CNAME ru.example.com.
Nginx: Virtual Hosts for Subdomains
# ru.example.com
server {
listen 443 ssl http2;
server_name ru.example.com;
root /var/www/example.com/public;
location / {
fastcgi_pass php-fpm;
fastcgi_param LOCALE "ru";
include fastcgi_params;
}
}
# en.example.com
server {
listen 443 ssl http2;
server_name en.example.com;
root /var/www/example.com/public;
location / {
fastcgi_pass php-fpm;
fastcgi_param LOCALE "en";
include fastcgi_params;
}
}
Application (Laravel): Locale Detection
// Middleware: LocaleFromSubdomain
class SetLocaleFromSubdomain
{
public function handle(Request $request, Closure $next): Response
{
$subdomain = explode('.', $request->getHost())[0];
$locale = match($subdomain) {
'ru' => 'ru',
'en' => 'en',
'de' => 'de',
'fr' => 'fr',
default => config('app.locale'),
};
App::setLocale($locale);
Carbon::setLocale($locale);
return $next($request);
}
}
hreflang for SEO
// In template: alternative versions for search engines
$locales = ['ru', 'en', 'de'];
foreach ($locales as $loc):
$url = "https://{$loc}.example.com" . request()->getPathInfo();
?>
<link rel="alternate" hreflang="<?= $loc ?>" href="<?= $url ?>" />
<?php endforeach; ?>
<link rel="alternate" hreflang="x-default" href="https://en.example.com<?= request()->getPathInfo() ?>" />
Redirect to Regional Subdomain
// Middleware: RedirectToRegionalSubdomain
class RedirectToRegionalSubdomain
{
public function handle(Request $request, Closure $next): Response
{
if ($request->getHost() === 'example.com') {
$locale = $this->detectLocale($request);
return redirect("https://{$locale}.example.com" . $request->getPathInfo(), 301);
}
return $next($request);
}
private function detectLocale(Request $request): string
{
// Priority: cookie → Accept-Language → GeoIP
if ($cookie = $request->cookie('preferred_locale')) return $cookie;
$acceptLanguage = $request->getPreferredLanguage(['ru', 'en', 'de', 'fr']);
return $acceptLanguage ?? 'en';
}
}
Timeline
Regional subdomains setup with Nginx, middleware and hreflang: 2–3 working days.







