DEV Community

ahmet gedik
ahmet gedik

Posted on

Building Multi-Language SEO for Video Aggregation Sites

Multi-language SEO goes far beyond translating meta tags. On TopVideoHub, which serves video content across 9 Asia-Pacific regions, I implemented a comprehensive SEO strategy for CJK and Southeast Asian languages.

The Multi-Language SEO Stack

  1. hreflang tags (covered in a previous article)
  2. Structured data with inLanguage
  3. Open Graph tags per region
  4. Dynamic meta descriptions
  5. CJK-aware title optimization
  6. Multi-language sitemap

Structured Data with VideoObject

Each video page includes Schema.org VideoObject markup with proper language tags:

function videoStructuredData(array $video, string $region): string {
    $locale = Region::from($region)->hreflang();

    $schema = [
        '@context' => 'https://schema.org',
        '@type' => 'VideoObject',
        'name' => $video['title'],
        'description' => $video['description'] ?? $video['title'],
        'thumbnailUrl' => $video['thumbnail_url'],
        'uploadDate' => $video['published_at'],
        'embedUrl' => "https://www.youtube.com/embed/{$video['video_id']}",
        'inLanguage' => $locale,
        'interactionStatistic' => [
            '@type' => 'InteractionCounter',
            'interactionType' => 'https://schema.org/WatchAction',
            'userInteractionCount' => $video['view_count'],
        ],
    ];

    return '<script type="application/ld+json">'
        . json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
        . '</script>';
}
Enter fullscreen mode Exit fullscreen mode

Key: JSON_UNESCAPED_UNICODE is essential. Without it, CJK characters get encoded as \uXXXX which some search engines handle poorly.

Region-Aware Meta Tags

class MetaGenerator {
    public function generate(string $page, ?string $region, array $data): array {
        $locale = $region ? Region::from($region)->hreflang() : 'en';

        return match($page) {
            'home' => $this->homeMeta($locale, $region),
            'category' => $this->categoryMeta($locale, $region, $data['category']),
            'watch' => $this->watchMeta($locale, $data['video']),
            default => $this->defaultMeta($locale),
        };
    }

    private function homeMeta(string $locale, ?string $region): array {
        $titles = [
            'en' => 'Trending Videos | TopVideoHub',
            'ja' => '人気動画トレンド | TopVideoHub',
            'ko' => '인기 동영상 트렌드 | TopVideoHub',
            'zh-TW' => '熱門影片趨勢 | TopVideoHub',
            'vi' => 'Video thịnh hành | TopVideoHub',
            'th' => 'วิดีโอยอดนิยม | TopVideoHub',
        ];

        $descriptions = [
            'en' => 'Discover the best trending videos from Japan, Korea, Taiwan, Singapore and more. Browse trending content across 9 Asia-Pacific regions.',
            'ja' => '日本、韓国、台湾、シンガポールなどアジア太平洋圣9地域のトレンド動画を発見。',
            'ko' => '일본, 한국, 대만, 싱가포르 등 아시아 태평양 9개 지역의 인기 동영상을 발견하세요.',
        ];

        return [
            'title' => $titles[$locale] ?? $titles['en'],
            'description' => $descriptions[$locale] ?? $descriptions['en'],
            'og:locale' => str_replace('-', '_', $locale),
        ];
    }

    private function watchMeta(string $locale, array $video): array {
        // For watch pages, use the video's actual title
        $title = mb_substr($video['title'], 0, 60) . ' | TopVideoHub';
        $desc = mb_substr($video['title'] . ' - ' . ($video['description'] ?? ''), 0, 155);

        return [
            'title' => $title,
            'description' => $desc,
            'og:type' => 'video.other',
            'og:video' => "https://www.youtube.com/embed/{$video['video_id']}",
            'og:image' => $video['thumbnail_url'],
            'og:locale' => str_replace('-', '_', $locale),
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

CJK Title Optimization

CJK titles have different optimal lengths than English:

function optimizeTitle(string $title, string $locale): string {
    $maxChars = match(true) {
        str_starts_with($locale, 'ja'),
        str_starts_with($locale, 'ko'),
        str_starts_with($locale, 'zh') => 30, // CJK: ~30 chars visible in SERP
        str_starts_with($locale, 'th'),
        str_starts_with($locale, 'vi') => 50, // Thai/Vietnamese: similar to Latin
        default => 60, // English/Latin: standard
    };

    $suffix = ' | TopVideoHub';
    $available = $maxChars - mb_strlen($suffix);

    if (mb_strlen($title) > $available) {
        $title = mb_substr($title, 0, $available - 1) . '…';
    }

    return $title . $suffix;
}
Enter fullscreen mode Exit fullscreen mode

Open Graph for Multi-Region Sharing

When someone shares a TopVideoHub link on social media, the OG tags should match the region:

function renderOGTags(array $meta): string {
    $tags = '';
    foreach ($meta as $property => $content) {
        if (str_starts_with($property, 'og:')) {
            $tags .= '<meta property="' . $property . '" content="'
                . htmlspecialchars($content) . '">' . "\n";
        }
    }
    return $tags;
}
Enter fullscreen mode Exit fullscreen mode

Multi-Language Sitemap

The sitemap includes hreflang references and language-appropriate lastmod dates:

function generateMultiLangSitemap(\PDO $db): string {
    $regions = ['US','GB','JP','KR','TW','SG','VN','TH','HK'];
    $baseUrl = 'https://topvideohub.com';

    $xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"' . "\n";
    $xml .= '  xmlns:xhtml="http://www.w3.org/1999/xhtml">' . "\n";

    // Home page with all regional variants
    $xml .= "  <url>\n    <loc>{$baseUrl}/</loc>\n";
    foreach ($regions as $r) {
        $lang = Region::from($r)->hreflang();
        $xml .= "    <xhtml:link rel=\"alternate\" hreflang=\"{$lang}\" href=\"{$baseUrl}/?region={$r}\"/>\n";
    }
    $xml .= "    <xhtml:link rel=\"alternate\" hreflang=\"x-default\" href=\"{$baseUrl}/\"/>\n";
    $xml .= "  </url>\n";

    $xml .= '</urlset>';
    return $xml;
}
Enter fullscreen mode Exit fullscreen mode

SEO Impact on TopVideoHub

After implementing full multi-language SEO on TopVideoHub:

  • Pages indexed by Google across 7+ regional search engines
  • Organic traffic from Asian search engines grew significantly
  • Google Search Console shows zero hreflang errors
  • Video rich results appearing in Google Japan and Korea

Multi-language SEO is not optional for platforms targeting Asia-Pacific. It's the difference between being invisible and being discoverable in the world's largest digital market.

Top comments (2)

Collapse
 
botanica_andina profile image
Botánica Andina

Love the breakdown of multi-language SEO beyond just hreflang. The VideoObject structured data with inLanguage is key for video sites. Have you noticed any specific indexing differences with inLanguage for CJK content versus Latin scripts, especially with dynamic descriptions?

Collapse
 
apex_stack profile image
Apex Stack

The CJK title length optimization is a detail most multilingual SEO guides completely skip, and it matters more than people think. I run a financial data platform across 12 languages (including Dutch, German, Japanese, French) with 8,000+ stock ticker pages per language, and the SERP display length difference between CJK and Latin scripts caught us off guard early on.

Your JSON_UNESCAPED_UNICODE point is critical too. We hit a related issue with structured data validation — Google's Rich Results Test would pass the escaped version but the actual rendering in search results would occasionally break for CJK characters, especially in breadcrumb markup. Switching to unescaped output fixed it silently.

One thing I'd add from our experience at scale: the hreflang sitemap approach works well until you cross ~50K URLs, at which point you need sitemap index files and the cross-referencing between language variants gets expensive to generate. We ended up pre-computing the hreflang mappings in our build step rather than generating them dynamically. With 9 regions you might not hit that ceiling yet, but if TopVideoHub's video catalog grows it'll sneak up on you.

Curious about your GSC data across regions — are you seeing certain languages index significantly faster than others? We found Dutch pages getting indexed and ranking before English ones, which was completely counterintuitive until we realized competition in smaller language markets is dramatically lower.