mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-26 12:08:15 +00:00
feat(host-control-mode): localize the in-page dialog & badge
The host-control desync dialog and the "watching on your own" badge were hardcoded English — content.js has no i18n loader. Background does, so it now resolves the strings (GET_HCM_STRINGS: loadLocale + getMessage) and content fetches them on init with English fallbacks, re-rendering the badge if it was already shown. The dialog body is now generic (dropped the paused/jumped verb) to keep translation clean across languages. Adds 6 keys (HCM_DIALOG_TITLE/BODY/STAY/SOLO, HCM_BADGE_SOLO/RESYNC) translated across all 15 popup locales. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -49,8 +49,9 @@ Deferred by decision (see §8): host grace period on disconnect (EC-10).
|
||||
- ~~**Control-mode race at join:**~~ FIXED — `hcmHandleBlocked` now treats `HOST_BLOCKED`
|
||||
as authoritative (adopts host-only/guest role) instead of re-checking local mode,
|
||||
since background only sends it to gated guests.
|
||||
- **Dialog/badge text is English-only** — content.js has no i18n loader; the in-page
|
||||
strings aren't localized yet. Follow-up.
|
||||
- ~~**Dialog/badge text is English-only**~~ FIXED — background resolves the strings
|
||||
via GET_HCM_STRINGS (it has the i18n loader); content fetches them on init with
|
||||
English fallback. 6 new keys (HCM_DIALOG_*/HCM_BADGE_*) across all 15 locales.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1731,6 +1731,20 @@ async function handleAsyncMessage(message, sender, sendResponse) {
|
||||
} else if (message.type === 'REQUEST_HOST_SYNC') {
|
||||
// content.js resync: hand back the host's extrapolated current position.
|
||||
sendResponse({ target: getHostSyncTarget() });
|
||||
} else if (message.type === 'GET_HCM_STRINGS') {
|
||||
// Localized strings for the in-page host-control dialog/badge. content.js
|
||||
// has no i18n loader of its own, so background resolves them here.
|
||||
const settings = await chrome.storage.local.get(['locale']);
|
||||
const lang = settings.locale || getSystemLanguage();
|
||||
await loadLocale(lang);
|
||||
sendResponse({
|
||||
title: getMessage('HCM_DIALOG_TITLE'),
|
||||
body: getMessage('HCM_DIALOG_BODY'),
|
||||
stay: getMessage('HCM_DIALOG_STAY'),
|
||||
solo: getMessage('HCM_DIALOG_SOLO'),
|
||||
badge: getMessage('HCM_BADGE_SOLO'),
|
||||
resync: getMessage('HCM_BADGE_RESYNC')
|
||||
});
|
||||
} else if (message.type === 'HCM_DESYNC_STATE') {
|
||||
// content.js tells us whether the local user chose to watch on their own.
|
||||
// Only accept from the currently selected tab.
|
||||
|
||||
+24
-6
@@ -115,6 +115,16 @@
|
||||
let hcmLastUserGestureAt = 0; // for deliberate-vs-involuntary classification
|
||||
let hcmBufferingUntil = 0; // set on 'waiting' — buffering grace window
|
||||
let hcmDialogTimer = null; // 8s auto-stay timer — cleared on dialog replace (H-4)
|
||||
// Localized strings for the in-page dialog/badge (content has no i18n loader;
|
||||
// background resolves them via GET_HCM_STRINGS on init). English fallbacks here.
|
||||
const hcmStrings = {
|
||||
title: 'KoalaSync · Host controls this room',
|
||||
body: 'Only the host can control playback in this room. Keep watching together, or watch on your own?',
|
||||
stay: 'Stay in sync',
|
||||
solo: 'Watch on my own',
|
||||
badge: 'Watching on your own',
|
||||
resync: 'Resync'
|
||||
};
|
||||
const HCM_USER_GESTURE_MS = 1000;
|
||||
const HCM_BUFFERING_GRACE_MS = 1500;
|
||||
const HCM_SNAP_BACK_COOLDOWN_MS = 1000;
|
||||
@@ -256,12 +266,11 @@
|
||||
|
||||
const wrap = hcmEl('div', 'position:fixed;z-index:2147483647;left:50%;bottom:32px;transform:translateX(-50%);background:#1f2937;color:#f9fafb;font:14px/1.4 system-ui,sans-serif;padding:16px 18px;border-radius:12px;box-shadow:0 8px 30px rgba(0,0,0,.45);max-width:360px;border:1px solid #374151');
|
||||
wrap.setAttribute('role', 'dialog');
|
||||
const verb = action === EVENTS.SEEK ? 'jumped' : 'paused';
|
||||
const title = hcmEl('div', 'font-weight:600;margin-bottom:6px', 'KoalaSync · Host controls this room');
|
||||
const body = hcmEl('div', 'margin-bottom:12px;color:#d1d5db', `You ${verb} your player. Only the host can control the group. Keep watching together, or watch on your own?`);
|
||||
const title = hcmEl('div', 'font-weight:600;margin-bottom:6px', hcmStrings.title);
|
||||
const body = hcmEl('div', 'margin-bottom:12px;color:#d1d5db', hcmStrings.body);
|
||||
const btnRow = hcmEl('div', 'display:flex;gap:8px;justify-content:flex-end');
|
||||
const soloBtn = hcmEl('button', 'background:#374151;color:#f9fafb;border:0;padding:8px 12px;border-radius:8px;cursor:pointer', 'Watch on my own');
|
||||
const stayBtn = hcmEl('button', 'background:#10b981;color:#062a20;border:0;padding:8px 12px;border-radius:8px;cursor:pointer;font-weight:600', 'Stay in sync');
|
||||
const soloBtn = hcmEl('button', 'background:#374151;color:#f9fafb;border:0;padding:8px 12px;border-radius:8px;cursor:pointer', hcmStrings.solo);
|
||||
const stayBtn = hcmEl('button', 'background:#10b981;color:#062a20;border:0;padding:8px 12px;border-radius:8px;cursor:pointer;font-weight:600', hcmStrings.stay);
|
||||
btnRow.append(soloBtn, stayBtn);
|
||||
wrap.append(title, body, btnRow);
|
||||
root.appendChild(wrap);
|
||||
@@ -326,7 +335,7 @@
|
||||
const host = hcmEl('div', 'all:initial');
|
||||
const root = host.attachShadow({ mode: 'open' });
|
||||
const b = hcmEl('div', 'position:fixed;z-index:2147483646;right:16px;bottom:16px;background:#b45309;color:#fff;font:13px/1.3 system-ui,sans-serif;padding:8px 12px;border-radius:10px;box-shadow:0 6px 20px rgba(0,0,0,.4);cursor:pointer;display:flex;align-items:center;gap:8px');
|
||||
b.append(hcmEl('span', null, '● Watching on your own'), hcmEl('span', 'text-decoration:underline', 'Resync'));
|
||||
b.append(hcmEl('span', null, '● ' + hcmStrings.badge), hcmEl('span', 'text-decoration:underline', hcmStrings.resync));
|
||||
b.addEventListener('click', hcmExitDesync);
|
||||
root.appendChild(b);
|
||||
document.body.appendChild(host);
|
||||
@@ -1448,4 +1457,13 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Pull localized strings for the in-page dialog/badge (English fallback above).
|
||||
chrome.runtime.sendMessage({ type: 'GET_HCM_STRINGS' }, (res) => {
|
||||
if (chrome.runtime.lastError || !res) return;
|
||||
Object.keys(hcmStrings).forEach(k => { if (res[k]) hcmStrings[k] = res[k]; });
|
||||
// If the badge is already showing (early desync), re-render it with the
|
||||
// localized text now that we have it.
|
||||
if (hcmBadgeHost) { hcmRemoveBadge(); hcmShowBadge(); }
|
||||
});
|
||||
|
||||
})();
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Gast",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Schaut alleine — ignoriert die Befehle des Hosts",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · Der Host steuert diesen Raum",
|
||||
"HCM_DIALOG_BODY": "Nur der Host kann die Wiedergabe in diesem Raum steuern. Weiter gemeinsam schauen oder allein weiterschauen?",
|
||||
"HCM_DIALOG_STAY": "Synchron bleiben",
|
||||
"HCM_DIALOG_SOLO": "Allein weiterschauen",
|
||||
"HCM_BADGE_SOLO": "Du schaust allein",
|
||||
"HCM_BADGE_RESYNC": "Neu sync",
|
||||
"NO_PEERS_CONNECTED": "Keine Teilnehmer verbunden",
|
||||
"BTN_LEAVE_ROOM": "Raum verlassen",
|
||||
"LABEL_SELECT_VIDEO": "Video auswählen",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Guest",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Watching on their own — host's commands are ignored",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · Host controls this room",
|
||||
"HCM_DIALOG_BODY": "Only the host can control playback in this room. Keep watching together, or watch on your own?",
|
||||
"HCM_DIALOG_STAY": "Stay in sync",
|
||||
"HCM_DIALOG_SOLO": "Watch on my own",
|
||||
"HCM_BADGE_SOLO": "Watching on your own",
|
||||
"HCM_BADGE_RESYNC": "Resync",
|
||||
"NO_PEERS_CONNECTED": "No peers connected",
|
||||
"BTN_LEAVE_ROOM": "Leave Room",
|
||||
"LABEL_SELECT_VIDEO": "Select Video",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Invitado",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Viendo por su cuenta — ignora los comandos del anfitrión",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · El anfitrión controla esta sala",
|
||||
"HCM_DIALOG_BODY": "Solo el anfitrión puede controlar la reproducción en esta sala. ¿Seguir viendo juntos o ver por tu cuenta?",
|
||||
"HCM_DIALOG_STAY": "Seguir sincronizado",
|
||||
"HCM_DIALOG_SOLO": "Ver por mi cuenta",
|
||||
"HCM_BADGE_SOLO": "Viendo por tu cuenta",
|
||||
"HCM_BADGE_RESYNC": "Resincronizar",
|
||||
"NO_PEERS_CONNECTED": "Sin participantes conectados",
|
||||
"BTN_LEAVE_ROOM": "Salir de la sala",
|
||||
"LABEL_SELECT_VIDEO": "Seleccionar video",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Invité",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Regarde de son côté — ignore les commandes de l'hôte",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · L'hôte contrôle ce salon",
|
||||
"HCM_DIALOG_BODY": "Seul l'hôte peut contrôler la lecture dans ce salon. Continuer à regarder ensemble, ou regarder de votre côté ?",
|
||||
"HCM_DIALOG_STAY": "Rester synchronisé",
|
||||
"HCM_DIALOG_SOLO": "Regarder de mon côté",
|
||||
"HCM_BADGE_SOLO": "Vous regardez seul",
|
||||
"HCM_BADGE_RESYNC": "Resynchroniser",
|
||||
"NO_PEERS_CONNECTED": "Aucun membre connecté",
|
||||
"BTN_LEAVE_ROOM": "Quitter le salon",
|
||||
"LABEL_SELECT_VIDEO": "Choisir une vidéo",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Ospite",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Guarda per conto proprio — ignora i comandi dell'host",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · L'host controlla questa stanza",
|
||||
"HCM_DIALOG_BODY": "Solo l'host può controllare la riproduzione in questa stanza. Continuare a guardare insieme o guardare per conto tuo?",
|
||||
"HCM_DIALOG_STAY": "Resta sincronizzato",
|
||||
"HCM_DIALOG_SOLO": "Guarda per conto mio",
|
||||
"HCM_BADGE_SOLO": "Stai guardando da solo",
|
||||
"HCM_BADGE_RESYNC": "Risincronizza",
|
||||
"NO_PEERS_CONNECTED": "Nessun partecipante connesso",
|
||||
"BTN_LEAVE_ROOM": "Lascia Stanza",
|
||||
"LABEL_SELECT_VIDEO": "Seleziona Video",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "ゲスト",
|
||||
"BADGE_DESYNCED": "ソロ",
|
||||
"TOOLTIP_PEER_DESYNCED": "単独で視聴中 — ホストのコマンドを無視しています",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · ホストがこのルームを操作中",
|
||||
"HCM_DIALOG_BODY": "このルームではホストのみが再生を操作できます。一緒に視聴を続けますか、それとも自分だけで視聴しますか?",
|
||||
"HCM_DIALOG_STAY": "同期を維持",
|
||||
"HCM_DIALOG_SOLO": "自分だけで視聴",
|
||||
"HCM_BADGE_SOLO": "自分だけで視聴中",
|
||||
"HCM_BADGE_RESYNC": "再同期",
|
||||
"NO_PEERS_CONNECTED": "接続しているメンバーはいません",
|
||||
"BTN_LEAVE_ROOM": "ルームを退室",
|
||||
"LABEL_SELECT_VIDEO": "ビデオを選択",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "게스트",
|
||||
"BADGE_DESYNCED": "단독",
|
||||
"TOOLTIP_PEER_DESYNCED": "혼자 시청 중 — 호스트 명령을 무시합니다",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · 호스트가 이 방을 제어합니다",
|
||||
"HCM_DIALOG_BODY": "이 방에서는 호스트만 재생을 제어할 수 있습니다. 계속 함께 보시겠어요, 아니면 혼자 보시겠어요?",
|
||||
"HCM_DIALOG_STAY": "동기화 유지",
|
||||
"HCM_DIALOG_SOLO": "혼자 보기",
|
||||
"HCM_BADGE_SOLO": "혼자 시청 중",
|
||||
"HCM_BADGE_RESYNC": "다시 동기화",
|
||||
"NO_PEERS_CONNECTED": "연결된 참여자가 없습니다",
|
||||
"BTN_LEAVE_ROOM": "방 나가기",
|
||||
"LABEL_SELECT_VIDEO": "비디오 선택",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Gast",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Zelfstandig aan het kijken — negeert de commando's van de host",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · De host bedient deze kamer",
|
||||
"HCM_DIALOG_BODY": "Alleen de host kan de weergave in deze kamer bedienen. Samen blijven kijken of zelf verder kijken?",
|
||||
"HCM_DIALOG_STAY": "Gesynchroniseerd blijven",
|
||||
"HCM_DIALOG_SOLO": "Zelf verder kijken",
|
||||
"HCM_BADGE_SOLO": "Je kijkt zelfstandig",
|
||||
"HCM_BADGE_RESYNC": "Opnieuw sync",
|
||||
"NO_PEERS_CONNECTED": "Geen deelnemers verbonden",
|
||||
"BTN_LEAVE_ROOM": "Kamer verlaten",
|
||||
"LABEL_SELECT_VIDEO": "Selecteer video",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Gość",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Ogląda samodzielnie — ignoruje polecenia hosta",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · Host steruje tym pokojem",
|
||||
"HCM_DIALOG_BODY": "Tylko host może sterować odtwarzaniem w tym pokoju. Oglądać dalej razem czy oglądać samodzielnie?",
|
||||
"HCM_DIALOG_STAY": "Pozostań zsynchronizowany",
|
||||
"HCM_DIALOG_SOLO": "Oglądaj samodzielnie",
|
||||
"HCM_BADGE_SOLO": "Oglądasz samodzielnie",
|
||||
"HCM_BADGE_RESYNC": "Zsynchronizuj",
|
||||
"NO_PEERS_CONNECTED": "Brak połączonych uczestników",
|
||||
"BTN_LEAVE_ROOM": "Opuść pokój",
|
||||
"LABEL_SELECT_VIDEO": "Wybierz wideo",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Convidado",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Assistindo por conta própria — ignora os comandos do anfitrião",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · O anfitrião controla esta sala",
|
||||
"HCM_DIALOG_BODY": "Somente o anfitrião pode controlar a reprodução nesta sala. Continuar assistindo juntos ou assistir por conta própria?",
|
||||
"HCM_DIALOG_STAY": "Manter sincronizado",
|
||||
"HCM_DIALOG_SOLO": "Assistir por conta própria",
|
||||
"HCM_BADGE_SOLO": "Assistindo por conta própria",
|
||||
"HCM_BADGE_RESYNC": "Ressincronizar",
|
||||
"NO_PEERS_CONNECTED": "Sem participantes conectados",
|
||||
"BTN_LEAVE_ROOM": "Sair da sala",
|
||||
"LABEL_SELECT_VIDEO": "Selecionar vídeo",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Convidado",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "A ver por conta própria — ignora os comandos do anfitrião",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · O anfitrião controla esta sala",
|
||||
"HCM_DIALOG_BODY": "Só o anfitrião pode controlar a reprodução nesta sala. Continuar a ver em conjunto ou ver por conta própria?",
|
||||
"HCM_DIALOG_STAY": "Manter sincronizado",
|
||||
"HCM_DIALOG_SOLO": "Ver por minha conta",
|
||||
"HCM_BADGE_SOLO": "A ver por tua conta",
|
||||
"HCM_BADGE_RESYNC": "Ressincronizar",
|
||||
"NO_PEERS_CONNECTED": "Nenhum participante ligado",
|
||||
"BTN_LEAVE_ROOM": "Sair da Sala",
|
||||
"LABEL_SELECT_VIDEO": "Selecionar Vídeo",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Гость",
|
||||
"BADGE_DESYNCED": "Соло",
|
||||
"TOOLTIP_PEER_DESYNCED": "Смотрит отдельно — игнорирует команды ведущего",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · Комнатой управляет ведущий",
|
||||
"HCM_DIALOG_BODY": "Управлять воспроизведением в этой комнате может только ведущий. Продолжить смотреть вместе или смотреть самостоятельно?",
|
||||
"HCM_DIALOG_STAY": "Оставаться синхронно",
|
||||
"HCM_DIALOG_SOLO": "Смотреть самостоятельно",
|
||||
"HCM_BADGE_SOLO": "Вы смотрите самостоятельно",
|
||||
"HCM_BADGE_RESYNC": "Синхронизировать",
|
||||
"NO_PEERS_CONNECTED": "Нет подключенных участников",
|
||||
"BTN_LEAVE_ROOM": "Выйти из комнаты",
|
||||
"LABEL_SELECT_VIDEO": "Выбрать видео",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Misafir",
|
||||
"BADGE_DESYNCED": "Solo",
|
||||
"TOOLTIP_PEER_DESYNCED": "Tek başına izliyor — sunucu komutlarını yok sayar",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · Bu odayı sunucu kontrol ediyor",
|
||||
"HCM_DIALOG_BODY": "Bu odada oynatmayı yalnızca sunucu kontrol edebilir. Birlikte izlemeye devam mı, yoksa kendi başına mı izlemek istiyorsun?",
|
||||
"HCM_DIALOG_STAY": "Senkron kal",
|
||||
"HCM_DIALOG_SOLO": "Kendi başıma izle",
|
||||
"HCM_BADGE_SOLO": "Kendi başına izliyorsun",
|
||||
"HCM_BADGE_RESYNC": "Yeniden senkronize et",
|
||||
"NO_PEERS_CONNECTED": "Bağlı kimse yok",
|
||||
"BTN_LEAVE_ROOM": "Odadan Ayrıl",
|
||||
"LABEL_SELECT_VIDEO": "Video Seç",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "Гість",
|
||||
"BADGE_DESYNCED": "Соло",
|
||||
"TOOLTIP_PEER_DESYNCED": "Дивиться окремо — ігнорує команди ведучого",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · Кімнатою керує ведучий",
|
||||
"HCM_DIALOG_BODY": "Керувати відтворенням у цій кімнаті може лише ведучий. Продовжити дивитися разом чи дивитися самостійно?",
|
||||
"HCM_DIALOG_STAY": "Залишатися синхронно",
|
||||
"HCM_DIALOG_SOLO": "Дивитися самостійно",
|
||||
"HCM_BADGE_SOLO": "Ви дивитеся самостійно",
|
||||
"HCM_BADGE_RESYNC": "Синхронізувати",
|
||||
"NO_PEERS_CONNECTED": "Немає підключених однорангових пристроїв",
|
||||
"BTN_LEAVE_ROOM": "Вийти з кімнати",
|
||||
"LABEL_SELECT_VIDEO": "Виберіть Відео",
|
||||
|
||||
@@ -52,6 +52,12 @@
|
||||
"BADGE_GUEST": "访客",
|
||||
"BADGE_DESYNCED": "单独",
|
||||
"TOOLTIP_PEER_DESYNCED": "单独观看中 — 忽略主持人的命令",
|
||||
"HCM_DIALOG_TITLE": "KoalaSync · 主持人控制本房间",
|
||||
"HCM_DIALOG_BODY": "本房间只有主持人可以控制播放。继续一起观看,还是自己单独观看?",
|
||||
"HCM_DIALOG_STAY": "保持同步",
|
||||
"HCM_DIALOG_SOLO": "自己单独观看",
|
||||
"HCM_BADGE_SOLO": "正在单独观看",
|
||||
"HCM_BADGE_RESYNC": "重新同步",
|
||||
"NO_PEERS_CONNECTED": "没有对等点连接",
|
||||
"BTN_LEAVE_ROOM": "离开房间",
|
||||
"LABEL_SELECT_VIDEO": "选择视频",
|
||||
|
||||
Reference in New Issue
Block a user