138 lines
5.3 KiB
TypeScript
138 lines
5.3 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import { useEffect } from 'react';
|
||
|
|
|
||
|
|
interface TDKProps {
|
||
|
|
title: string;
|
||
|
|
description: string;
|
||
|
|
keywords: string;
|
||
|
|
lang: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export default function TDK({ title, description, keywords, lang }: TDKProps) {
|
||
|
|
useEffect(() => {
|
||
|
|
// Update document title
|
||
|
|
document.title = title;
|
||
|
|
|
||
|
|
// Update meta description
|
||
|
|
let metaDesc = document.querySelector('meta[name="description"]');
|
||
|
|
if (!metaDesc) {
|
||
|
|
metaDesc = document.createElement('meta');
|
||
|
|
metaDesc.setAttribute('name', 'description');
|
||
|
|
document.head.appendChild(metaDesc);
|
||
|
|
}
|
||
|
|
metaDesc.setAttribute('content', description);
|
||
|
|
|
||
|
|
// Update meta keywords
|
||
|
|
let metaKeywords = document.querySelector('meta[name="keywords"]');
|
||
|
|
if (!metaKeywords) {
|
||
|
|
metaKeywords = document.createElement('meta');
|
||
|
|
metaKeywords.setAttribute('name', 'keywords');
|
||
|
|
document.head.appendChild(metaKeywords);
|
||
|
|
}
|
||
|
|
metaKeywords.setAttribute('content', keywords);
|
||
|
|
|
||
|
|
// Update language meta tag
|
||
|
|
let metaLang = document.querySelector('meta[http-equiv="Content-Language"]');
|
||
|
|
if (!metaLang) {
|
||
|
|
metaLang = document.createElement('meta');
|
||
|
|
metaLang.setAttribute('http-equiv', 'Content-Language');
|
||
|
|
document.head.appendChild(metaLang);
|
||
|
|
}
|
||
|
|
metaLang.setAttribute('content', lang);
|
||
|
|
|
||
|
|
// Add hreflang tags for language alternatives
|
||
|
|
const supportedLangs = ['en', 'zh-CN', 'zh-TW', 'ko', 'ja'];
|
||
|
|
|
||
|
|
// Remove existing hreflang tags
|
||
|
|
document.querySelectorAll('link[rel="alternate"][hreflang]').forEach((el) => el.remove());
|
||
|
|
|
||
|
|
// Add new hreflang tags
|
||
|
|
const baseUrl = window.location.origin;
|
||
|
|
supportedLangs.forEach((supportedLang) => {
|
||
|
|
const hreflangLink = document.createElement('link');
|
||
|
|
hreflangLink.setAttribute('rel', 'alternate');
|
||
|
|
hreflangLink.setAttribute('hreflang', supportedLang);
|
||
|
|
hreflangLink.setAttribute('href', `${baseUrl}/${supportedLang}`);
|
||
|
|
document.head.appendChild(hreflangLink);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Add x-default hreflang
|
||
|
|
const xDefaultLink = document.createElement('link');
|
||
|
|
xDefaultLink.setAttribute('rel', 'alternate');
|
||
|
|
xDefaultLink.setAttribute('hreflang', 'x-default');
|
||
|
|
xDefaultLink.setAttribute('href', `${baseUrl}/en`);
|
||
|
|
document.head.appendChild(xDefaultLink);
|
||
|
|
|
||
|
|
// Update canonical URL
|
||
|
|
let canonicalLink = document.querySelector('link[rel="canonical"]');
|
||
|
|
if (!canonicalLink) {
|
||
|
|
canonicalLink = document.createElement('link');
|
||
|
|
canonicalLink.setAttribute('rel', 'canonical');
|
||
|
|
document.head.appendChild(canonicalLink);
|
||
|
|
}
|
||
|
|
canonicalLink.setAttribute('href', window.location.href.split('?')[0]);
|
||
|
|
|
||
|
|
// Add Open Graph meta tags
|
||
|
|
let ogTitle = document.querySelector('meta[property="og:title"]');
|
||
|
|
if (!ogTitle) {
|
||
|
|
ogTitle = document.createElement('meta');
|
||
|
|
ogTitle.setAttribute('property', 'og:title');
|
||
|
|
document.head.appendChild(ogTitle);
|
||
|
|
}
|
||
|
|
ogTitle.setAttribute('content', title);
|
||
|
|
|
||
|
|
let ogDesc = document.querySelector('meta[property="og:description"]');
|
||
|
|
if (!ogDesc) {
|
||
|
|
ogDesc = document.createElement('meta');
|
||
|
|
ogDesc.setAttribute('property', 'og:description');
|
||
|
|
document.head.appendChild(ogDesc);
|
||
|
|
}
|
||
|
|
ogDesc.setAttribute('content', description);
|
||
|
|
|
||
|
|
let ogUrl = document.querySelector('meta[property="og:url"]');
|
||
|
|
if (!ogUrl) {
|
||
|
|
ogUrl = document.createElement('meta');
|
||
|
|
ogUrl.setAttribute('property', 'og:url');
|
||
|
|
document.head.appendChild(ogUrl);
|
||
|
|
}
|
||
|
|
ogUrl.setAttribute('content', window.location.href);
|
||
|
|
|
||
|
|
let ogType = document.querySelector('meta[property="og:type"]');
|
||
|
|
if (!ogType) {
|
||
|
|
ogType = document.createElement('meta');
|
||
|
|
ogType.setAttribute('property', 'og:type');
|
||
|
|
document.head.appendChild(ogType);
|
||
|
|
}
|
||
|
|
ogType.setAttribute('content', 'website');
|
||
|
|
|
||
|
|
// Add Twitter Card meta tags
|
||
|
|
let twitterCard = document.querySelector('meta[name="twitter:card"]');
|
||
|
|
if (!twitterCard) {
|
||
|
|
twitterCard = document.createElement('meta');
|
||
|
|
twitterCard.setAttribute('name', 'twitter:card');
|
||
|
|
document.head.appendChild(twitterCard);
|
||
|
|
}
|
||
|
|
twitterCard.setAttribute('content', 'summary_large_image');
|
||
|
|
|
||
|
|
let twitterTitle = document.querySelector('meta[name="twitter:title"]');
|
||
|
|
if (!twitterTitle) {
|
||
|
|
twitterTitle = document.createElement('meta');
|
||
|
|
twitterTitle.setAttribute('name', 'twitter:title');
|
||
|
|
document.head.appendChild(twitterTitle);
|
||
|
|
}
|
||
|
|
twitterTitle.setAttribute('content', title);
|
||
|
|
|
||
|
|
let twitterDesc = document.querySelector('meta[name="twitter:description"]');
|
||
|
|
if (!twitterDesc) {
|
||
|
|
twitterDesc = document.createElement('meta');
|
||
|
|
twitterDesc.setAttribute('name', 'twitter:description');
|
||
|
|
document.head.appendChild(twitterDesc);
|
||
|
|
}
|
||
|
|
twitterDesc.setAttribute('content', description);
|
||
|
|
}, [title, description, keywords, lang]);
|
||
|
|
|
||
|
|
// This component doesn't render anything visible
|
||
|
|
return null;
|
||
|
|
}
|