Add multilingual SEO support in routes-seo.js</message>
<message> - Introduced a new SEO_LOCALES array to support multiple languages for SEO content. - Implemented a function to build multilingual SEO content based on available locale files. - Enhanced the generateHTML function to include multilingual sections for the home route, improving accessibility for diverse audiences. These changes enhance the site's SEO capabilities by providing localized content for better search engine indexing and user engagement.
This commit is contained in:
@@ -4,6 +4,17 @@ import { loadFeedback } from './feedback-store.js';
|
||||
|
||||
const SITE_URL = 'https://www.ypchat.net';
|
||||
const DEFAULT_IMAGE = `${SITE_URL}/static/favicon.png`;
|
||||
const SEO_LOCALES = [
|
||||
{ code: 'de', label: 'Deutsch' },
|
||||
{ code: 'en', label: 'English' },
|
||||
{ code: 'fr', label: 'Francais' },
|
||||
{ code: 'es', label: 'Espanol' },
|
||||
{ code: 'it', label: 'Italiano' },
|
||||
{ code: 'ja', label: 'Japanese' },
|
||||
{ code: 'zh', label: 'Chinese' },
|
||||
{ code: 'th', label: 'Thai' },
|
||||
{ code: 'tl', label: 'Tagalog' }
|
||||
];
|
||||
|
||||
const seoData = {
|
||||
'/': {
|
||||
@@ -212,6 +223,45 @@ function upsertJsonLd(html, schema) {
|
||||
return html.replace('</head>', ` ${tag}\n</head>`);
|
||||
}
|
||||
|
||||
function sanitizeLocalizedHtml(input = '') {
|
||||
return String(input)
|
||||
.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, '')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function buildMultilingualSeoContent(__dirname) {
|
||||
const localesDir = join(__dirname, '../client/src/i18n/locales');
|
||||
const blocks = [];
|
||||
|
||||
for (const locale of SEO_LOCALES) {
|
||||
const filePath = join(localesDir, `${locale.code}.json`);
|
||||
if (!existsSync(filePath)) continue;
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(readFileSync(filePath, 'utf-8'));
|
||||
const welcome = sanitizeLocalizedHtml(parsed.welcome || '');
|
||||
const intro = sanitizeLocalizedHtml(parsed.introduction || '');
|
||||
if (!welcome && !intro) continue;
|
||||
|
||||
blocks.push(`<section lang="${escapeHtml(locale.code)}" style="margin-bottom:20px;">
|
||||
<h2 style="font:600 22px/1.2 sans-serif;color:#18201b;margin:0 0 10px;">${escapeHtml(locale.label)}</h2>
|
||||
${welcome}
|
||||
${intro}
|
||||
</section>`);
|
||||
} catch (error) {
|
||||
console.warn(`[SEO] Locale konnte nicht gelesen werden (${locale.code}): ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (blocks.length === 0) return '';
|
||||
|
||||
return `<section style="max-width:960px;margin:24px auto;padding:0 16px;">
|
||||
<h2 style="font:600 28px/1.15 sans-serif;color:#18201b;margin:0 0 12px;">Mehrsprachige Inhalte</h2>
|
||||
<p style="font:400 15px/1.5 sans-serif;color:#4f5d54;margin:0 0 18px;">Diese Texte sind serverseitig eingebettet, damit Suchmaschinen die Inhalte in allen verfügbaren Sprachen direkt erfassen können.</p>
|
||||
${blocks.join('\n')}
|
||||
</section>`;
|
||||
}
|
||||
|
||||
function generateHTML(route, meta, __dirname) {
|
||||
const distIndexPath = join(__dirname, '../docroot/dist/index.html');
|
||||
|
||||
@@ -244,6 +294,13 @@ function generateHTML(route, meta, __dirname) {
|
||||
html = upsertLinkTag(html, 'canonical', meta.ogUrl);
|
||||
html = upsertJsonLd(html, meta.schema);
|
||||
|
||||
if (route === '/') {
|
||||
const multilingual = buildMultilingualSeoContent(__dirname);
|
||||
if (multilingual) {
|
||||
html = html.replace('<div id="app"></div>', `<div id="app">${multilingual}</div>`);
|
||||
}
|
||||
}
|
||||
|
||||
if (route === '/feedback') {
|
||||
const feedbackItems = loadFeedback(__dirname)
|
||||
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
|
||||
|
||||
Reference in New Issue
Block a user