diff --git a/eslint.config.mjs b/eslint.config.mjs index da21dc6..5f2f9f5 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -8,6 +8,7 @@ export default [ sourceType: "module", globals: { chrome: "readonly", + browser: "readonly", window: "readonly", document: "readonly", navigator: "readonly", diff --git a/extension/locales/de.json b/extension/locales/de.json index 42c1b11..6703db2 100644 --- a/extension/locales/de.json +++ b/extension/locales/de.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Equalizer", "AUDIO_COMING_SOON": "Demnächst", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Einführung neu starten", + "BTN_RESTART_TOUR_TOOLTIP": "Startet die Einführung für neue Benutzer erneut", + "HINT_SELECT_VIDEO": "Wähle hier dein Video aus!" } diff --git a/extension/locales/es.json b/extension/locales/es.json index 97b4495..98415e2 100644 --- a/extension/locales/es.json +++ b/extension/locales/es.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Ecualizador", "AUDIO_COMING_SOON": "Próximamente", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Reiniciar tutorial", + "BTN_RESTART_TOUR_TOOLTIP": "Reiniciar el tutorial de inicio", + "HINT_SELECT_VIDEO": "¡Selecciona tu video aquí!" } diff --git a/extension/locales/fr.json b/extension/locales/fr.json index 83ad29c..e5e7122 100644 --- a/extension/locales/fr.json +++ b/extension/locales/fr.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Égaliseur", "AUDIO_COMING_SOON": "Bientôt disponible", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Redémarrer le tutoriel", + "BTN_RESTART_TOUR_TOOLTIP": "Recommencer le tutoriel d'intégration", + "HINT_SELECT_VIDEO": "Sélectionnez votre vidéo ici !" } diff --git a/extension/locales/it.json b/extension/locales/it.json index c1af1cc..002fdee 100644 --- a/extension/locales/it.json +++ b/extension/locales/it.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Equalizzatore", "AUDIO_COMING_SOON": "Prossimamente", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Riavvia tutorial", + "BTN_RESTART_TOUR_TOOLTIP": "Riavvia il tutorial iniziale", + "HINT_SELECT_VIDEO": "Seleziona il tuo video qui!" } diff --git a/extension/locales/ja.json b/extension/locales/ja.json index bbcff90..7237ef8 100644 --- a/extension/locales/ja.json +++ b/extension/locales/ja.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "イコライザー", "AUDIO_COMING_SOON": "近日公開", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "チュートリアルを再起動", + "BTN_RESTART_TOUR_TOOLTIP": "オンボーディングチュートリアルを再起動する", + "HINT_SELECT_VIDEO": "ここで動画を選択してください!" } diff --git a/extension/locales/ko.json b/extension/locales/ko.json index fe61d49..d0c6f11 100644 --- a/extension/locales/ko.json +++ b/extension/locales/ko.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "이퀄라이저", "AUDIO_COMING_SOON": "출시 예정", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "튜토리얼 다시 시작", + "BTN_RESTART_TOUR_TOOLTIP": "온보딩 튜토리얼을 다시 시작합니다", + "HINT_SELECT_VIDEO": "여기에서 비디오를 선택하세요!" } diff --git a/extension/locales/nl.json b/extension/locales/nl.json index 7ea5786..37d18e0 100644 --- a/extension/locales/nl.json +++ b/extension/locales/nl.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Equalizer", "AUDIO_COMING_SOON": "Binnenkort beschikbaar", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Tutorial opnieuw starten", + "BTN_RESTART_TOUR_TOOLTIP": "Start de introductie-tutorial opnieuw", + "HINT_SELECT_VIDEO": "Selecteer hier je video!" } diff --git a/extension/locales/pl.json b/extension/locales/pl.json index 24f0eb2..fa7d561 100644 --- a/extension/locales/pl.json +++ b/extension/locales/pl.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Korektor", "AUDIO_COMING_SOON": "Wkrótce", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Uruchom samouczek ponownie", + "BTN_RESTART_TOUR_TOOLTIP": "Uruchom ponownie samouczek powitalny", + "HINT_SELECT_VIDEO": "Wybierz swoje wideo tutaj!" } diff --git a/extension/locales/pt-BR.json b/extension/locales/pt-BR.json index f15f2d6..aa417c1 100644 --- a/extension/locales/pt-BR.json +++ b/extension/locales/pt-BR.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Equalizador", "AUDIO_COMING_SOON": "Em breve", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Reiniciar tutorial", + "BTN_RESTART_TOUR_TOOLTIP": "Reiniciar o tutorial de introdução", + "HINT_SELECT_VIDEO": "Selecione seu vídeo aqui!" } diff --git a/extension/locales/pt.json b/extension/locales/pt.json index 8250a52..f761222 100644 --- a/extension/locales/pt.json +++ b/extension/locales/pt.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Equalizador", "AUDIO_COMING_SOON": "Em breve", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Reiniciar tutorial", + "BTN_RESTART_TOUR_TOOLTIP": "Reiniciar o tutorial de introdução", + "HINT_SELECT_VIDEO": "Selecione o seu vídeo aqui!" } diff --git a/extension/locales/ru.json b/extension/locales/ru.json index b7ed9f2..c7429d7 100644 --- a/extension/locales/ru.json +++ b/extension/locales/ru.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Эквалайзер", "AUDIO_COMING_SOON": "Скоро", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Перезапустить обучение", + "BTN_RESTART_TOUR_TOOLTIP": "Запустить приветственное руководство заново", + "HINT_SELECT_VIDEO": "Выберите ваше видео здесь!" } diff --git a/extension/locales/tr.json b/extension/locales/tr.json index 0529502..855e35a 100644 --- a/extension/locales/tr.json +++ b/extension/locales/tr.json @@ -206,7 +206,7 @@ "AUDIO_PARAM_RELEASE": "Release", "AUDIO_EQUALIZER": "Ekolayzer", "AUDIO_COMING_SOON": "Çok yakında", - "BTN_RESTART_TOUR": "", - "BTN_RESTART_TOUR_TOOLTIP": "", - "HINT_SELECT_VIDEO": "" + "BTN_RESTART_TOUR": "Eğitimi Yeniden Başlat", + "BTN_RESTART_TOUR_TOOLTIP": "Tanıtım eğitimini yeniden başlat", + "HINT_SELECT_VIDEO": "Videonuzu buradan seçin!" } diff --git a/scripts/build-extension.js b/scripts/build-extension.js index 3709925..ffcb971 100644 --- a/scripts/build-extension.js +++ b/scripts/build-extension.js @@ -106,7 +106,7 @@ function copyExtensionFiles(targetDir, browserName) { const uStart = '// --- UNINSTALL_URL_INJECT_START ---'; const uEnd = '// --- UNINSTALL_URL_INJECT_END ---'; const uPattern = new RegExp(`${uStart}[\\s\\S]+?${uEnd}`); - const placeholderUrl = "https://example.com/uninstall-placeholder"; // TODO: Replace me + const placeholderUrl = "https://bye.koalastuff.net/c/camp_99ztjRVbK1BNN2RU"; let uRep = `${uStart}\n // This block is automatically updated by /scripts/build-extension.js\n`; uRep += ` const UNINSTALL_URL = "${placeholderUrl}";\n`; diff --git a/scripts/test-locales.js b/scripts/test-locales.js index 81bac1a..d6df537 100644 --- a/scripts/test-locales.js +++ b/scripts/test-locales.js @@ -48,7 +48,7 @@ try { const enDict = JSON.parse(fs.readFileSync(enPath, 'utf8')); const enKeys = Object.keys(enDict); -const localeFiles = fs.readdirSync(localesDir).filter(file => file.endsWith('.json') && file !== 'en.json'); +const localeFiles = fs.readdirSync(localesDir).filter(file => file.endsWith('.json')); console.log(`Auditing i18n locales using ${enKeys.length} baseline keys from en.json...\n`); @@ -79,8 +79,21 @@ for (const file of localeFiles) { const missingKeys = enKeys.filter(k => !keys.includes(k)); const extraKeys = keys.filter(k => !enKeys.includes(k)); + const emptyKeys = keys.filter(k => typeof dict[k] === 'string' && dict[k].trim() === ''); + const placeholderKeys = keys.filter(k => { + if (typeof dict[k] !== 'string') return false; + const val = dict[k]; + const lower = val.toLowerCase(); + return ( + lower.includes('placeholder') || + lower.includes('todo:') || + lower.includes('tbd:') || + /\bTODO\b/.test(val) || + /\bTBD\b/.test(val) + ); + }); - if (missingKeys.length > 0 || extraKeys.length > 0) { + if (missingKeys.length > 0 || extraKeys.length > 0 || emptyKeys.length > 0 || placeholderKeys.length > 0) { hasError = true; console.error(`❌ ${file} has inconsistencies:`); if (missingKeys.length > 0) { @@ -89,6 +102,12 @@ for (const file of localeFiles) { if (extraKeys.length > 0) { console.error(` Extra keys (${extraKeys.length}):`, extraKeys); } + if (emptyKeys.length > 0) { + console.error(` Empty translation values (${emptyKeys.length}):`, emptyKeys); + } + if (placeholderKeys.length > 0) { + console.error(` Placeholder/TODO values (${placeholderKeys.length}):`, placeholderKeys); + } } else { console.log(`✓ ${file} is fully consistent (matches all keys).`); } diff --git a/scripts/test-website-locales.mjs b/scripts/test-website-locales.mjs index b4bd9b3..02d0e42 100644 --- a/scripts/test-website-locales.mjs +++ b/scripts/test-website-locales.mjs @@ -17,7 +17,7 @@ const enDict = JSON.parse(fs.readFileSync(enPath, 'utf8')); const enKeys = Object.keys(enDict).sort(); const localeFiles = fs.readdirSync(localesDir) - .filter(file => file.endsWith('.json') && file !== 'en.json') + .filter(file => file.endsWith('.json')) .sort(); let hasError = false; @@ -51,8 +51,24 @@ for (const file of localeFiles) { const missingKeys = enKeys.filter(k => !keys.includes(k)); const extraKeys = keys.filter(k => !enKeys.includes(k)); + const emptyKeys = keys.filter(k => { + if (file === 'en.json' && k === 'CANONICAL_PATH') return false; + return typeof dict[k] === 'string' && dict[k].trim() === ''; + }); + const placeholderKeys = keys.filter(k => { + if (typeof dict[k] !== 'string') return false; + const val = dict[k]; + const lower = val.toLowerCase(); + return ( + lower.includes('placeholder') || + lower.includes('todo:') || + lower.includes('tbd:') || + /\bTODO\b/.test(val) || + /\bTBD\b/.test(val) + ); + }); - if (missingKeys.length > 0 || extraKeys.length > 0) { + if (missingKeys.length > 0 || extraKeys.length > 0 || emptyKeys.length > 0 || placeholderKeys.length > 0) { hasError = true; console.error(`❌ ${file} has inconsistencies:`); if (missingKeys.length > 0) { @@ -61,6 +77,12 @@ for (const file of localeFiles) { if (extraKeys.length > 0) { console.error(` Extra keys (${extraKeys.length}):`, extraKeys); } + if (emptyKeys.length > 0) { + console.error(` Empty translation values (${emptyKeys.length}):`, emptyKeys); + } + if (placeholderKeys.length > 0) { + console.error(` Placeholder/TODO values (${placeholderKeys.length}):`, placeholderKeys); + } } else { console.log(`✓ ${file} is fully consistent (matches all keys).`); } diff --git a/website/locales/it.json b/website/locales/it.json index e901b70..7191af3 100644 --- a/website/locales/it.json +++ b/website/locales/it.json @@ -2,7 +2,7 @@ "LANG_CODE": "it", "HTML_CLASS": "lang-it", "CANONICAL_PATH": "it/", - "LANG_TOGGLE_URL": "", + "LANG_TOGGLE_URL": "../", "LANG_TOGGLE_TEXT": "EN", "OG_LOCALE": "it_IT", "META_TITLE": "KoalaSync | Sincronizza Netflix, YouTube e qualsiasi video con gli amici", diff --git a/website/locales/ja.json b/website/locales/ja.json index 49eb8ed..eae29e3 100644 --- a/website/locales/ja.json +++ b/website/locales/ja.json @@ -2,7 +2,7 @@ "LANG_CODE": "ja", "HTML_CLASS": "lang-ja", "CANONICAL_PATH": "ja/", - "LANG_TOGGLE_URL": "", + "LANG_TOGGLE_URL": "../", "LANG_TOGGLE_TEXT": "EN", "OG_LOCALE": "ja_JP", "META_TITLE": "KoalaSync | Netflix、YouTube、あらゆる動画を友達と同期視聴", diff --git a/website/locales/ko.json b/website/locales/ko.json index 39fb942..3ae5173 100644 --- a/website/locales/ko.json +++ b/website/locales/ko.json @@ -2,7 +2,7 @@ "LANG_CODE": "ko", "HTML_CLASS": "lang-ko", "CANONICAL_PATH": "ko/", - "LANG_TOGGLE_URL": "", + "LANG_TOGGLE_URL": "../", "LANG_TOGGLE_TEXT": "EN", "OG_LOCALE": "ko_KR", "META_TITLE": "KoalaSync | Netflix, YouTube 및 모든 비디오를 친구와 실시간 동기화 시청", diff --git a/website/locales/nl.json b/website/locales/nl.json index d141c55..c07f65a 100644 --- a/website/locales/nl.json +++ b/website/locales/nl.json @@ -2,7 +2,7 @@ "LANG_CODE": "nl", "HTML_CLASS": "lang-nl", "CANONICAL_PATH": "nl/", - "LANG_TOGGLE_URL": "", + "LANG_TOGGLE_URL": "../", "LANG_TOGGLE_TEXT": "EN", "OG_LOCALE": "nl_NL", "META_TITLE": "KoalaSync | Synchroniseer Netflix, YouTube & elke video met vrienden", diff --git a/website/locales/pl.json b/website/locales/pl.json index a216060..479e7fc 100644 --- a/website/locales/pl.json +++ b/website/locales/pl.json @@ -2,7 +2,7 @@ "LANG_CODE": "pl", "HTML_CLASS": "lang-pl", "CANONICAL_PATH": "pl/", - "LANG_TOGGLE_URL": "", + "LANG_TOGGLE_URL": "../", "LANG_TOGGLE_TEXT": "EN", "OG_LOCALE": "pl_PL", "META_TITLE": "KoalaSync | Synchronizuj Netflix, YouTube i dowolne wideo ze znajomymi", diff --git a/website/locales/pt.json b/website/locales/pt.json index 19a3365..4a4889b 100644 --- a/website/locales/pt.json +++ b/website/locales/pt.json @@ -2,7 +2,7 @@ "LANG_CODE": "pt", "HTML_CLASS": "lang-pt", "CANONICAL_PATH": "pt/", - "LANG_TOGGLE_URL": "", + "LANG_TOGGLE_URL": "../", "LANG_TOGGLE_TEXT": "EN", "OG_LOCALE": "pt_PT", "META_TITLE": "KoalaSync | Sincronize Netflix, YouTube e qualquer vídeo com os amigos", diff --git a/website/locales/tr.json b/website/locales/tr.json index bbf5bbd..1758864 100644 --- a/website/locales/tr.json +++ b/website/locales/tr.json @@ -2,7 +2,7 @@ "LANG_CODE": "tr", "HTML_CLASS": "lang-tr", "CANONICAL_PATH": "tr/", - "LANG_TOGGLE_URL": "", + "LANG_TOGGLE_URL": "../", "LANG_TOGGLE_TEXT": "EN", "OG_LOCALE": "tr_TR", "META_TITLE": "KoalaSync | Netflix, YouTube ve Herhangi Bir Videoyu Arkadaşlarınızla Eşitleyin",