mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-08-27 11:07:07 +00:00
feat(alternatives): add Teleparty & Screen Sharing comparison pages with i18n
- Add article-style comparison pages for Teleparty and Screen Sharing - Replace comparison tables with honest prose sections - Add 15-language hreflang alternates and sitemap entries - Add English locale fallback for untranslated languages - Replace placeholder Draft copy with real English and German text - Remove old Draft locale keys from all 13 non-EN/DE locales - Rebuild outputs with zero TODO/Draft/noindex issues
This commit is contained in:
+84
-11
@@ -174,6 +174,8 @@ async function compile() {
|
||||
let compiled = templateContent;
|
||||
compiled = compiled.replace(/\{\{ASSET_PATH\}\}/g, assetPath);
|
||||
compiled = compiled.replace(/\{\{VERSION\}\}/g, buildVersion);
|
||||
const langPrefix = lang === 'en' ? '' : `${lang}/`;
|
||||
compiled = compiled.replace(/\{\{LANG_PREFIX\}\}/g, langPrefix);
|
||||
languages.forEach(l => {
|
||||
compiled = compiled.replace(new RegExp(`\\{\\{SELECTED_${l.toUpperCase()}\\}\\}`, 'g'), l === lang ? 'selected' : '');
|
||||
});
|
||||
@@ -183,6 +185,44 @@ async function compile() {
|
||||
return compiled;
|
||||
}
|
||||
|
||||
// Read alternative page templates
|
||||
const telepartyTemplatePath = path.join(websiteDir, 'alternatives/teleparty.html');
|
||||
const screenSharingTemplatePath = path.join(websiteDir, 'alternatives/screen-sharing.html');
|
||||
const overviewTemplatePath = path.join(websiteDir, 'alternatives/index.html');
|
||||
const hasTelepartyTemplate = fs.existsSync(telepartyTemplatePath);
|
||||
const hasScreenSharingTemplate = fs.existsSync(screenSharingTemplatePath);
|
||||
const hasOverviewTemplate = fs.existsSync(overviewTemplatePath);
|
||||
const telepartyTemplate = hasTelepartyTemplate ? fs.readFileSync(telepartyTemplatePath, 'utf8') : '';
|
||||
const screenSharingTemplate = hasScreenSharingTemplate ? fs.readFileSync(screenSharingTemplatePath, 'utf8') : '';
|
||||
const overviewTemplate = hasOverviewTemplate ? fs.readFileSync(overviewTemplatePath, 'utf8') : '';
|
||||
|
||||
// Preload English locale for fallback
|
||||
const englishLocalePath = path.join(localesDir, 'en.json');
|
||||
const englishLocale = JSON.parse(fs.readFileSync(englishLocalePath, 'utf8'));
|
||||
|
||||
function compileAlternativePage(templateContent, locale, lang, assetPath, langPrefix) {
|
||||
let compiled = templateContent;
|
||||
compiled = compiled.replace(/\{\{LANG_CODE\}\}/g, lang);
|
||||
compiled = compiled.replace(/\{\{ASSET_PATH\}\}/g, assetPath);
|
||||
compiled = compiled.replace(/\{\{LANG_PREFIX\}\}/g, langPrefix);
|
||||
compiled = compiled.replace(/\{\{VERSION\}\}/g, buildVersion);
|
||||
|
||||
const indexTitle = lang === 'de' ? 'KoalaSync - Vergleiche & Anleitungen' : 'KoalaSync - Alternatives & Comparisons';
|
||||
const indexDesc = lang === 'de'
|
||||
? 'Entdecke ehrliche Vergleiche und detaillierte Leitfäden zwischen KoalaSync und anderen Watch-Party-Erweiterungen.'
|
||||
: 'Explore honest comparisons and detailed guides comparing KoalaSync with other watch party extensions and streaming solutions.';
|
||||
|
||||
compiled = compiled.replace(/\{\{ALT_INDEX_TITLE\}\}/g, indexTitle);
|
||||
compiled = compiled.replace(/\{\{ALT_INDEX_META_DESC\}\}/g, indexDesc);
|
||||
|
||||
// Merge locale with English fallback for keys not present in current locale
|
||||
const mergedLocale = { ...englishLocale, ...locale };
|
||||
for (const [key, value] of Object.entries(mergedLocale)) {
|
||||
compiled = compiled.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value);
|
||||
}
|
||||
return compiled;
|
||||
}
|
||||
|
||||
for (const lang of languages) {
|
||||
const localePath = path.join(localesDir, `${lang}.json`);
|
||||
if (!fs.existsSync(localePath)) { console.warn(`Warning: Locale ${lang} not found.`); continue; }
|
||||
@@ -193,6 +233,26 @@ async function compile() {
|
||||
const html = compilePage(locale, '', lang);
|
||||
fs.writeFileSync(path.join(wwwDir, 'index.html'), html);
|
||||
englishHtml[''] = html;
|
||||
|
||||
// Compile alternatives for English (assets resolved using '../' prefix)
|
||||
if (hasTelepartyTemplate) {
|
||||
const altDir = path.join(wwwDir, 'alternatives');
|
||||
fs.mkdirSync(altDir, { recursive: true });
|
||||
const tpCompiled = compileAlternativePage(telepartyTemplate, locale, lang, '../', '');
|
||||
fs.writeFileSync(path.join(altDir, 'teleparty.html'), tpCompiled);
|
||||
}
|
||||
if (hasScreenSharingTemplate) {
|
||||
const altDir = path.join(wwwDir, 'alternatives');
|
||||
fs.mkdirSync(altDir, { recursive: true });
|
||||
const ssCompiled = compileAlternativePage(screenSharingTemplate, locale, lang, '../', '');
|
||||
fs.writeFileSync(path.join(altDir, 'screen-sharing.html'), ssCompiled);
|
||||
}
|
||||
if (hasOverviewTemplate) {
|
||||
const altDir = path.join(wwwDir, 'alternatives');
|
||||
fs.mkdirSync(altDir, { recursive: true });
|
||||
const ovCompiled = compileAlternativePage(overviewTemplate, locale, lang, '../', '');
|
||||
fs.writeFileSync(path.join(altDir, 'index.html'), ovCompiled);
|
||||
}
|
||||
} else {
|
||||
console.log(`Compiling ${lang.toUpperCase()} (${lang}/index.html)...`);
|
||||
const langDir = path.join(wwwDir, lang);
|
||||
@@ -200,6 +260,26 @@ async function compile() {
|
||||
const html = compilePage(locale, '../', lang);
|
||||
fs.writeFileSync(path.join(langDir, 'index.html'), html);
|
||||
englishHtml[lang] = html;
|
||||
|
||||
// Compile alternatives for other languages (assets resolved using '../../' prefix)
|
||||
if (hasTelepartyTemplate) {
|
||||
const langAltDir = path.join(langDir, 'alternatives');
|
||||
fs.mkdirSync(langAltDir, { recursive: true });
|
||||
const tpCompiled = compileAlternativePage(telepartyTemplate, locale, lang, '../../', lang + '/');
|
||||
fs.writeFileSync(path.join(langAltDir, 'teleparty.html'), tpCompiled);
|
||||
}
|
||||
if (hasScreenSharingTemplate) {
|
||||
const langAltDir = path.join(langDir, 'alternatives');
|
||||
fs.mkdirSync(langAltDir, { recursive: true });
|
||||
const ssCompiled = compileAlternativePage(screenSharingTemplate, locale, lang, '../../', lang + '/');
|
||||
fs.writeFileSync(path.join(langAltDir, 'screen-sharing.html'), ssCompiled);
|
||||
}
|
||||
if (hasOverviewTemplate) {
|
||||
const langAltDir = path.join(langDir, 'alternatives');
|
||||
fs.mkdirSync(langAltDir, { recursive: true });
|
||||
const ovCompiled = compileAlternativePage(overviewTemplate, locale, lang, '../../', lang + '/');
|
||||
fs.writeFileSync(path.join(langAltDir, 'index.html'), ovCompiled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +299,7 @@ async function compile() {
|
||||
const src = path.join(websiteDir, mapping.src);
|
||||
const dest = path.join(wwwDir, mapping.dest);
|
||||
if (fs.existsSync(src)) {
|
||||
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||
fs.copyFileSync(src, dest);
|
||||
console.log(` Copied: ${mapping.src} → ${mapping.dest}`);
|
||||
}
|
||||
@@ -278,23 +359,15 @@ async function compile() {
|
||||
let html = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// 8a. Replace hashed asset refs
|
||||
html = html.replace(/href="(?:\.\.\/)?style\.min\.css"/g, (m) => {
|
||||
const prefix = m.includes('../') ? '../' : '';
|
||||
html = html.replace(/href="((?:\.\.\/)*)style\.min\.css"/g, (m, prefix) => {
|
||||
return `href="${prefix}${styleName}"`;
|
||||
});
|
||||
html = html.replace(/src="(?:\.\.\/)?app\.min\.js"/g, (m) => {
|
||||
const prefix = m.includes('../') ? '../' : '';
|
||||
html = html.replace(/src="((?:\.\.\/)*)app\.min\.js"/g, (m, prefix) => {
|
||||
return `src="${prefix}${appName}"`;
|
||||
});
|
||||
html = html.replace(/src="(?:\.\.\/)?lang-init\.min\.js"/g, (m) => {
|
||||
const prefix = m.includes('../') ? '../' : '';
|
||||
html = html.replace(/src="((?:\.\.\/)*)lang-init\.min\.js"/g, (m, prefix) => {
|
||||
return `src="${prefix}${langName}"`;
|
||||
});
|
||||
// Also update preload directives
|
||||
html = html.replace(/href="(?:\.\.\/)?style\.min\.css"/g, (m) => {
|
||||
const prefix = m.includes('../') ? '../' : '';
|
||||
return `href="${prefix}${styleName}"`;
|
||||
});
|
||||
|
||||
// 8b. Inject AVIF <picture> wrappers
|
||||
html = injectAvifPictures(html);
|
||||
|
||||
Reference in New Issue
Block a user