Compare commits

...

83 Commits

Author SHA1 Message Date
KoalaDev cb84709358 fix(popup): render lobby peer names as text, not markup
Peer usernames are remote-controlled and were interpolated into an
innerHTML string in updateLobbyUI. The server only truncates them to 30
chars, so a peer could inject markup into everyone else's popup: enough
to load a remote image (leaking viewer IPs) or spoof readiness badges.
Inline handlers were already blocked by the MV3 default CSP.

Build the peer items with the DOM API, matching the pattern the sibling
peer list already uses.

Add the two checks that would have caught this before upload:
- eslint no-unsanitized, which reproduces the AMO warning at lint time
- addons-linter on the built XPI in verify-release, with
  --warnings-as-errors since it exits 0 on warnings and AMO rejects them

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 05:57:38 +02:00
KoalaDev 43a7bb0d57 docs: scope changelog header to extension and relay server
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 05:16:58 +02:00
KoalaDev e1e86307b1 docs: drop redesign-era items from v2.6.0 Fixed
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 05:16:45 +02:00
KoalaDev e934fcf484 docs: limit v2.6.0 changelog to extension and server
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 05:16:16 +02:00
GitHub Action d4181b2eaf chore(release): update versions to v2.6.0 [skip ci] 2026-07-15 03:14:35 +00:00
KoalaDev 66d650f49c docs: date v2.6.0 changelog release
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 05:13:43 +02:00
KoalaDev 2cde14b260 Merge pull request #28 from Shik3i/redesign/koala-nature-theme
Redesign the website and extension with the Koala nature theme
2026-07-15 05:03:48 +02:00
KoalaDev db8bf8f647 docs: remove em dashes from store copy 2026-07-15 04:58:51 +02:00
KoalaDev 81001f2890 docs: correct relay and self-hosting copy 2026-07-15 04:55:53 +02:00
KoalaDev 861ffc306a test(website): validate canonical relay URL 2026-07-15 04:53:29 +02:00
KoalaDev 6f6aac9c18 docs: refresh project documentation 2026-07-15 04:45:45 +02:00
KoalaDev e4984b2d03 fix(website): complete self-hosting example 2026-07-15 04:37:51 +02:00
KoalaDev 18205f6573 docs(website): expand AI project profile 2026-07-15 04:29:20 +02:00
KoalaDev a4bbddf3a4 fix(website): address accessibility audit findings 2026-07-15 04:23:14 +02:00
KoalaDev b577f06988 fix(website): restore light mode step numbers 2026-07-15 03:48:22 +02:00
KoalaDev 61514b9b6f fix(website): generate sitemap only in build output 2026-07-15 03:30:22 +02:00
Timo 62046acb81 fix(ci): preserve optional lockfile entries 2026-07-14 16:38:47 +02:00
Timo 8b6a1412cc fix(build): replace regex HTML minifier 2026-07-14 16:30:13 +02:00
Timo 6e5a790707 fix(website): restore GitHub hero button outline 2026-07-14 16:11:50 +02:00
Timo 0f4b1d7217 docs(release): prepare v2.6.0 changelog and sitemap 2026-07-14 13:58:24 +02:00
Timo af0da75d38 style(website): landing motion, interaction & layout polish
Feedback round (calmer, less "template/AI"):
- Dial back animated background motion globally (sway/leaf-drift halved,
  fewer falling leaves, gentler godrays/fireflies/light-sweep).
- Fire leaf confetti on click of real controls only (was pointerdown
  everywhere, which showered mobile users on every scroll).
- Remove hover lift/scale from non-interactive cards, screenshots and
  mascots so they no longer read as clickable.
- Fix mobile nav menu colours in the light theme (was a hard-coded dark
  panel with low-contrast links).
- Calm how-it-works steps 1-2 (no button pulse/shine/cursor bob); step 3
  keeps its lively sync animation. Remove the now-static "copied" toast
  from step 1 since it only made sense mid-animation.

UX audit follow-ups:
- Unify vertical rhythm with one section-padding scale; vertically centre
  the hero so space is balanced instead of pooling under the CTAs.
- Split the mixed "Why KoalaSync?" grid into use-case scenarios and a
  labelled "Features" subsection, and move the #features nav anchor there.
- Demote the hero GitHub CTA to a quiet text link (Chrome > Firefox >
  GitHub hierarchy); scale down oversized section mascots and give them a
  shared soft shadow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 02:43:05 +02:00
Timo 63414bfcdd fix: strip all parenthesized/bracketed leading numbers in tab title normalization 2026-07-12 17:54:54 +02:00
Timo af1b66c6b7 fix: support multi-digit plus notification badges while preserving large numeric titles 2026-07-12 17:43:20 +02:00
Timo cc96fc1771 fix: support (99+) style notification badges in tab title normalization 2026-07-12 17:29:33 +02:00
Timo 9e8a446d97 fix: resolve Episode Lobby stuck loading state and prevent triggers on non-episodic media 2026-07-12 16:57:06 +02:00
Timo b987d13612 fix(extension): localize theme and appearance tooltips and selector options 2026-07-12 14:54:00 +02:00
Timo c175364f9a chore(website): refresh generated assets 2026-07-12 13:13:47 +02:00
Timo 0168484382 style(extension): unify control system and accessibility 2026-07-12 13:04:23 +02:00
Timo 99ecf9c9a8 fix(extension): normalize primary action labels 2026-07-12 12:17:32 +02:00
Timo f58ab54f45 fix(extension): remove redundant status accent bar 2026-07-12 12:15:21 +02:00
Timo 104602edec fix(extension): unify status UX and theme design 2026-07-12 11:10:15 +02:00
Timo 9d6a3650c4 fix(extension): polish settings selects and dark palette 2026-07-12 11:02:14 +02:00
Timo 986b2a6e56 style(extension): redesign settings and color system 2026-07-12 10:59:19 +02:00
Timo fdf20b6bf6 style(website): declutter background and polish stacked hero on small screens
- thin out bamboo/leaf/firefly decor in tiers (<=1440 / <=1024 / <=768px)
  so nothing moves behind the text column and copy stays readable
- center the single-column hero below 1024px (text, koala, CTAs, trust
  line) and let the odd CTA button span the full grid row
- remove the periodic wind gusts; keep the constant gentle bamboo sway
- reword the German demo CTA to "Live-Demo ansehen"

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 10:59:00 +02:00
KoalaDev 3ce64b8c41 style(website): place footer-ram at top of footer and adjust vertical margins 2026-07-12 06:55:32 +02:00
KoalaDev 6f8bc40023 style(website): swap footer-ram above copyright and apply unified small disclaimer style 2026-07-12 06:53:21 +02:00
KoalaDev 6f203405f9 fix(website): restore missing footer-disclaimer class styling to landing-primary.css 2026-07-12 06:52:34 +02:00
KoalaDev 949075b267 style(website): optimize header scroll-shrink and clean up footer styles/hover effects 2026-07-12 06:50:37 +02:00
KoalaDev 4fb8e0f53a style(extension): apply UI/UX audit enhancements, consolidate footers, and style capsule badges 2026-07-12 06:38:26 +02:00
KoalaDev bd33ea4804 feat(extension): implement accordion mutual exclusion behavior for settings details categories 2026-07-12 06:31:24 +02:00
KoalaDev 9cd3fc1ee2 feat(extension): redesign settings tab into 4 collapsible accordion groups with chevron indicator and hover effects 2026-07-12 06:28:34 +02:00
KoalaDev 44f9a78bb0 perf(website): migrate forest parallax to native CSS scroll-driven animations, fix step contrast, and resolve forced reflows 2026-07-12 06:18:58 +02:00
KoalaDev e27319908d refactor(website): apply day/night sky palette variables to sync theater illustration and video canvas 2026-07-12 05:48:27 +02:00
KoalaDev af4ac943a9 Landing performance: flag font subset, responsive mascots, AVIF cache, HTML minify
- Flag font: ship a committed fontTools subset (43 KB, -45%) of
  TwemojiCountryFlags.woff2 with only the 15 flags the site uses, under a
  content-hashed name with a preload on every flag-bearing page. The build
  validates the subset against a manifest and fails when a new flag
  appears without regenerating (npm run subset-flags). JS subsetters
  (subset-font/harfbuzzjs) were rejected: their wasm builds silently drop
  the COLR/CPAL color tables, rendering all flags invisible.
- Responsive mascots: legal/join/404 pages served 434-500px sources for
  175-180px slots; the build now emits 180w/360w variants (AVIF 1x: ~7 KB
  vs ~22 KB) and the pages use srcset. Small logo spots (14-42px) now use
  the existing 64/128px variants instead of the 256px file.
- injectAvifPictures copies the img sizes attribute onto the AVIF
  <source>; without it Chrome mis-selects w-descriptor candidates and can
  drop the image entirely.
- AVIF conversion is cached by content hash (.avif-cache.json); the old
  mtime check never hit because copyDirSync refreshes mtimes, so every
  verify re-encoded all 26 files.
- HTML output is minified (comments + indentation, <pre> preserved,
  newlines kept for inline-script safety): index.html 121 KB -> 93 KB.
- unicode-range trimmed to U+1F1E6-1F1FF; tag-sequence flags fall through
  to the system emoji font.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 04:34:53 +02:00
KoalaDev 9fd4e870f3 Update theme test after film bird removal
The test still required 4 foreground film birds, but commit 16cb138
deliberately removed them all; now it guards against remnants instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 04:34:36 +02:00
KoalaDev 16cb138eeb Remove film birds; fix language pill highlight
Strip every bird from the demo mockups: both hero video tabs and both
step-3 player scenes lose the background flock (.film-birds) and the
foreground flapping bird (.film-hero-bird), plus all related CSS in
styles/demo.css and the dead style.legacy.css.

Language selector: the <select> was 30px narrower than its pill, so in
appearance:base-select the click/focus highlight covered only the inner
~110px ("half the box"). Move the padding from the container onto the
control so it fills the pill edge-to-edge; mirror the fix in the mobile
legal.css override.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 03:57:18 +02:00
KoalaDev 17c9da292c Fix Getting Started light theme 2026-07-12 03:37:07 +02:00
KoalaDev c7c124dac7 Improve animated film bird 2026-07-12 03:28:05 +02:00
KoalaDev ea0970df72 Guard landing CSS cascade stability 2026-07-11 18:10:59 +02:00
KoalaDev 7614534818 Restore landing CSS cascade stability 2026-07-11 16:11:31 +02:00
KoalaDev 72d4f04526 Split landing CSS by render priority 2026-07-11 15:48:09 +02:00
KoalaDev 7fea11de0a Polish extension and landing page UI 2026-07-11 11:21:47 +02:00
KoalaDev fbef3d180c Give light theme proper green bamboo and a frosted language pill
- Bamboo layers get their own light-mode recipes (fresh greens, visible
  segment rings, sheen) instead of dark-theme gradients faded to 45%
- Language selector pill: frosted white glass, light dropdown/picker
  (was hard-coded dark glass in both themes)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 10:24:18 +02:00
KoalaDev fecaa8b54d Fix bamboo parallax direction: layers follow the scroll, not oppose it
Scrolling down now moves all bamboo layers up-screen with the content
(near fastest, far slowest) instead of pushing them down against it.
Vertical overscan flipped from top (-70%) to bottom (-40%) so the
upward drift never exposes a gap at the viewport bottom.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 10:20:38 +02:00
KoalaDev 8175f82f0b Polish demo film, bamboo forest, popup a11y, and step-1 toast
- Demo mockup video: drifting clouds, shooting star, moon craters, bird
  flock, valley mist band, floating lantern instead of bouncing ball,
  stronger cinematic vignette
- Player controls: play/pause glyph, duration, buffered range, volume,
  HD badge, fullscreen icon
- Bamboo background: two faint centre trunks, segment rings on far
  stalks, wider near stalks with extra leaf, smaller blurred layers
  (240% -> 200%) and reduced blur radii for cheaper compositing
- Step-1 illustration: invite toast floats fully below the popup card
- Extension popup: label/for associations for all settings controls
- Demo video select: drop invalid inline SVG inside <option>

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 10:10:37 +02:00
Timo 04df35bbe6 Enhance forest scene with mid bamboo layer, butterflies, click confetti, and demo scene polish 2026-07-11 06:08:12 +02:00
KoalaDev 21383b8b9c Polish animated forest background 2026-07-10 20:42:54 +02:00
KoalaDev 9cddac47ef Make forest parallax continuous and add scroll-depth journey
The drift clamp saturated after ~2600px, so nothing moved on long
pages. The vertical drift now maps scroll progress (0..1 over the full
document) onto the stalks' overscan, so the parallax runs end to end.

Turn the background into a descent through the forest: god-ray light
shafts and the canopy fade out while a dusk tint, thicker mist, the
terracotta horizon glow and the fireflies fade in as you scroll down.
Fireflies additionally wander organically (independent translate
property composing with their scale pulse), and on hover-capable
devices the bamboo layers tilt subtly toward the cursor. All layers
animate transform/opacity only, rAF-throttled, reduced-motion safe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 19:42:23 +02:00
KoalaDev 1f1844e99b Fix bamboo stalk taper and align stray colors to palette
The stalks used border-radius:50%, which renders a tall ellipse whose
ends taper to points, and unbounded parallax drift pushed them off the
bottom of the viewport on long pages. Rounded caps + 20% overscan +
a viewport-relative drift clamp keep them full-height while scrolling.

Sweep the remaining off-palette colors into the nature palette:
content-script overlays (slate grays), amber warnings/badges/star
accents (now terracotta) in popup, background badge and website
illustrations, and the support-heart red (now --danger).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 19:28:50 +02:00
KoalaDev aa52d319e1 Redesign website and extension with koala nature theme
v3.0.0 "The Greens Update" palette: forest-green oklch color system
(accent green + terracotta secondary) replaces the indigo/slate scheme
across the landing page and the extension popup/options. The blob
background becomes an animated bamboo forest overlay (parallax stalks,
falling leaves, canopy, ground mist, fireflies, light sweep, grain)
with prefers-reduced-motion support. Layout, structure and copy are
unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 19:18:40 +02:00
KoalaDev 05246ac485 Fix light mode step text contrast 2026-07-09 17:25:20 +02:00
KoalaDev 6412a9e6ff Unify website section canvas 2026-07-09 17:07:23 +02:00
KoalaDev ee1c2947ce Fix join mobile navigation toggle 2026-07-09 14:47:29 +02:00
KoalaDev df8133fb5b Avoid persisting passive language visits 2026-07-09 14:40:44 +02:00
KoalaDev e25ae25bbb Respect system theme on website 2026-07-09 14:38:09 +02:00
KoalaDev 1d049e1745 perf(website): fix startup forced reflow and adjust AVIF compression quality to 65 2026-07-09 05:12:46 +02:00
KoalaDev 6aa42668e9 feat(website): add SRI to scripts & styles and optimize hero image preload 2026-07-09 05:06:35 +02:00
KoalaDev 71fdea78f3 feat(website): optimize rendering performance and improve structured metadata 2026-07-09 04:53:07 +02:00
Timo 5b7ee654e4 fix(website): keep hero demo hint readable 2026-07-08 20:22:20 +02:00
KoalaDev 7718885511 seo(website): add comprehensive AI agent rules to .gitignore 2026-07-08 17:31:02 +02:00
KoalaDev 12bca85356 build(website): move locales translation utility to scripts/ and add validate-brand-names script 2026-07-08 17:28:11 +02:00
KoalaDev b4bf297a5b i18n(website): translate new alternatives pages in all languages and save translation script as workspace example 2026-07-08 17:26:41 +02:00
KoalaDev 1e417e3379 fix(website): wrap locale replacement values in function to prevent RegExp dollar replacement bugs 2026-07-08 16:59:04 +02:00
KoalaDev d7d795f076 build(website): integrate dynamic sitemap generation into main build script 2026-07-08 16:53:57 +02:00
KoalaDev a45cfb063e seo(website): regenerate sitemap.xml to index all alternatives and update llms.txt 2026-07-08 16:52:46 +02:00
KoalaDev ee28f9d275 fix(website): grammar in TwoSeven German locale 2026-07-08 16:51:08 +02:00
KoalaDev 21936e7f71 feat(website): add KoalaSync vs TwoSeven comparison page 2026-07-08 16:50:05 +02:00
KoalaDev a45e52c6ee feat(website): add KoalaSync vs Kosmi comparison page 2026-07-08 16:47:29 +02:00
KoalaDev a0b4f1a2bb feat(website): update Scener comparison with pricing and technical differences 2026-07-08 16:38:40 +02:00
KoalaDev 4a8fdfbe70 chore: remove obsolete LANDINGPAGE_UI_OVERHAUL_PLAN.md 2026-07-08 16:32:31 +02:00
KoalaDev 9127b1f8dd feat(website): add KoalaSync vs Scener comparison page 2026-07-08 16:27:04 +02:00
KoalaDev e3a27db611 docs: add v2.5.4 changelog entry 2026-07-08 16:26:17 +02:00
GitHub Action 861bb05ec2 chore(release): update versions to v2.5.4 [skip ci] 2026-07-08 14:25:32 +00:00
105 changed files with 21560 additions and 7646 deletions
+1 -5
View File
@@ -114,17 +114,13 @@ jobs:
sed -i "s/New v[0-9]\+\.[0-9]\+\.[0-9]\+ Release/New v$VERSION Release/g" README.md
echo " ✓ README.md -> v$VERSION"
# 7. website/sitemap.xml — lastmod dates
sed -i "s/<lastmod>[0-9-]*<\/lastmod>/<lastmod>$(date +%Y-%m-%d)<\/lastmod>/g" website/sitemap.xml
echo " ✓ website/sitemap.xml -> lastmod $(date +%Y-%m-%d)"
echo "Version injection complete."
- name: Commit and push version updates back to main
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add extension/manifest.base.json shared/constants.js package.json website/version.json website/template.html README.md website/sitemap.xml
git add extension/manifest.base.json shared/constants.js package.json website/version.json website/template.html README.md
git commit -m "chore(release): update versions to $GITHUB_REF_NAME [skip ci]" || echo "No changes to commit"
git push origin HEAD:main
env:
+16
View File
@@ -43,6 +43,22 @@ extension/shared/
# Auto-generated website build output
website/www/
website/.avif-cache.json
# Temporary scratch files
scratch/
# AI Assistants and Agents
.agents/
.antigravity/
.gemini/
.claude/
.codex/
.opencode/
.cursor/
.cursorrules
.copilot/
.cline/
.clinerules
.windsurfrules
.codeium/
-153
View File
@@ -1,153 +0,0 @@
> **TEMPORÄR:** Diese Datei dient nur der gemeinsamen Planung des Landingpage-UI-Overhauls
> auf dem Branch `landingpage-ui-overhaul`. Sie ist **kein** Teil des finalen Features und
> **muss vor dem Öffnen des PRs wieder gelöscht werden**.
# Landingpage UI Overhaul — Hero Mockup
## Ausgangslage
Die Landingpage (`website/template.html`, `website/style.css`, `website/app.js`, kompiliert
via `website/build.cjs` nach `website/www/`) ist bereits sehr gut, soll aber **statisch und
backend-frei** bleiben. Einziger Fokus dieses Overhauls: das rechte Hero-Mockup
(`.hero-mockup-wrapper` / `.extension-mockup`, `template.html:304-579`).
**Heutiger Zustand:** Ein 1:1-Nachbau des Extension-Popups mit 4 Tabs (Room / Sync /
Settings / Status). Tab-Wechsel nur per Klick (`app.js:391-407`), keine Animationen, kein
Auto-Play, kein Bezug zu den eigentlichen Video-Tabs, die synchronisiert werden.
## Ziel
Ein dynamischeres, platzoptimiertes Hero-Visual, das das Kernversprechen von KoalaSync
("zwei Browser-Tabs synchron abspielen") direkt zeigt — mit echten Animationen, einem
automatischen Durchlauf beim ersten Sichtbarwerden und voller manueller Bedienbarkeit
danach. Auf Mobile (Bildschirmgröße) bleibt exakt das heutige, statische Popup-Mockup
erhalten — kein neues Mobile-Design nötig, kein zusätzlicher Wartungsaufwand dort.
## Getroffene Entscheidungen (aus Rückfrage-Runde)
1. **Layout:** Gestapelt/Layered — zwei Browser-Tab-Karten leicht versetzt im Hintergrund
(Tiefeneffekt via `transform`/`box-shadow`), Extension-Popup öffnet sich als Overlay
davor/darüber.
2. **Tab-Inhalt:** Abstraktes Video-Mock — Gradient-Placeholder als "Video", Play-Button,
Fortschrittsbalken, Timestamp. Kein echtes Videomaterial, keine Marken/Logos, im
bestehenden minimalistischen `mock-*`-Stil.
3. **Auto-Play-Verhalten:** Einmaliger Durchlauf beim Sichtbarwerden (IntersectionObserver),
danach reiner manueller Modus. Kein Endlos-Loop im Hintergrund.
4. **Popup-Umfang:** Alle 4 Tabs (Room/Sync/Settings/Status) bleiben inhaltlich unverändert
— nur in die neue Animations-/Overlay-Logik eingebettet, kein Content-Kahlschlag.
## Vorgeschlagenes Storyboard (einmaliger Auto-Durchlauf)
1. **Ausgangszustand:** Zwei Tab-Karten ("Tab A" / "Tab B") sichtbar, Video-Mocks pausiert,
Fortschrittsbalken bei 0. Popup geschlossen, nur ein kleiner Launcher-Button sichtbar.
2. Popup öffnet sich (scale/slide-in) vor den Tab-Karten.
3. Simulierter Klick auf "Play" im Sync-Tab → beide Tab-Karten starten gleichzeitig
(Fortschrittsbalken laufen synchron), begleitet von einem kurzen "Sync-Pulse"
(Glow/Connection-Line) zwischen den beiden Karten.
4. Nach ein paar Sekunden: simulierter Klick auf "Pause" → beide Tabs pausieren synchron.
5. Popup schließt sich, Endzustand bleibt stehen (beide Tabs pausiert, synchron,
"Synced"-Indikator dezent sichtbar) — kein Reset auf Ausgangszustand.
6. **Danach/parallel volle manuelle Steuerung:**
- Klick auf eine Tab-Karte togglet deren eigenes Play/Pause *unabhängig* — spielt eine
Karte allein, laufen die Fortschrittsbalken bewusst auseinander ("out of sync"), um den
Schmerzpunkt zu illustrieren, den KoalaSync löst.
- Klick auf Play/Pause im Popup synchronisiert immer beide Tabs.
- Popup lässt sich jederzeit manuell öffnen/schließen, Tabs (Room/Sync/Settings/Status)
bleiben wie heute klickbar.
- Jede manuelle Interaktion während des Auto-Durchlaufs bricht diesen sofort ab und
übergibt die volle Kontrolle.
## Technischer Ansatz (Vorschlag)
- **Keine neuen Dependencies** — reines Vanilla JS + CSS, passend zur "Zero-Dependency"-
Philosophie des Projekts (siehe `website/README.md`).
- **Eine "Director"-Funktion** in `app.js`, die exakt dieselben Click-Handler wie die
manuelle Bedienung aufruft (kein doppelter Code-Pfad zwischen Auto- und Manual-Modus).
- **IntersectionObserver** triggert den einmaligen Durchlauf beim ersten Sichtbarwerden.
- **`prefers-reduced-motion`**: Auto-Durchlauf und Cursor-Ripple-Indikatoren werden
übersprungen, Endzustand wird direkt gesetzt (Pattern existiert bereits in
`style.css:2915-2939`).
- **Kein DOM-Duplikat für Mobile:** Das Popup-Markup bleibt eine einzige Quelle. Der neue
`.hero-mockup-dynamic`-Wrapper enthält die Tab-Karten + das Popup; unterhalb des
bestehenden Breakpoints (768px, siehe `style.css:1913`) werden die Tab-Karten und
Animationen per CSS ausgeblendet, das Popup fällt optisch auf das heutige, statische
Erscheinungsbild zurück, JS initialisiert dort keine Animationen. Vermeidet doppelte
i18n-Pflege der ~270 Zeilen Popup-Markup.
- **i18n-Vorsicht:** 15 Locale-Dateien unter `website/locales/*.json`. Neue sichtbare Texte
(Tab-Labels etc.) nach Möglichkeit vermeiden oder wie bestehende Mock-Inhalte
(z. B. "CoolUsername", "Stranger Things - S4E1") als nicht-lokalisierte Platzhalter
behandeln, um Übersetzungsaufwand in 15 Sprachen zu vermeiden. Neue `{{MOCK_XX}}`-Keys nur
falls wirklich nötig, dann mit Übersetzung in allen 15 Dateien.
- **Build:** Änderungen nur in den Source-Dateien (`template.html`, `style.css`, `app.js`),
niemals in `website/www/**` (generiert via `website/build.cjs`).
## Detailentscheidungen (bei der Umsetzung getroffen)
- [x] Breakpoint Mobile-Fallback: bestehende 768px übernommen (`matchMedia('(min-width: 769px)')`
im JS, `@media (max-width: 768px)` im CSS).
- [x] Auto-Durchlauf-Timing: Start ~1,4s nach 45% Sichtbarkeit (IntersectionObserver), dann
Cursor → Launcher → Sync-Tab → Play (läuft ~3s synchron) → Pause → Popup schließt.
Gesamtdauer ca. 10s.
- [x] Tab-Karten haben User-Badges passend zur Peer-Liste im Popup: "CoolUsername" (indigo)
und "KoalaPC" (grün), gleicher Episodentitel "Stranger Things - S4E1".
- [x] Echter animierter Ghost-Mauszeiger (SVG-Cursor mit Klick-Ripple), kein reiner
Ripple-Indikator — verkauft den Durchlauf deutlich besser.
- [x] Keine externe Referenz — eigener Stil, konsistent mit dem bestehenden `mock-*`-Design.
- [x] ~~Drift-Konzept~~ **Verworfen nach Feedback** — es stellte die Extension falsch dar
(als bräuchte sie das offene Popup). Ersetzt durch das **Broadcast-Modell**: Play/
Pause/Seek auf *irgendeinem* Video wird automatisch zum Peer gespiegelt (Puls wandert
über die Verbindungslinie, Peer folgt ~260ms später, Engine gleicht die Zeit an). Der
Status-Chip bleibt grün "In sync" und blitzt bei jedem Broadcast kurz das Event auf
("▶ CoolUsername", "❚❚ KoalaPC", "» …" für Seek). Das Popup ist nur die Fernbedienung
obendrauf, nie Voraussetzung.
- [x] Rework 2 nach Feedback: Kein reservierter Popup-Platz mehr; KoalaSync-Icon als
Extension-Button in der Toolbar des vorderen Fensters; Fortschrittsbalken klickbar
(Seek wird mitgesynct, Scrub-Thumb bei Hover).
- [x] Rework 3 nach Feedback: Fenster-Kaskade statt starker Überlappung — das **rechte**
Fenster (CoolUsername, mit dem Toolbar-Icon oben rechts) liegt im Vordergrund, das
linke (KoalaPC) versetzt dahinter unten links. Das Popup öffnet **rechts außen**
(right: 0, verankert unterm Icon), die beiden Tabs weichen dabei animiert nach links
aus und bleiben sichtbar. Verbindungslinie komplett entfernt (Sync-Feedback = Puls-
Ring auf beiden Karten + Event-Chip). Peer-Latenz von 260ms auf 90ms gesenkt — wirkt
quasi instant.
- [x] Rework 4 nach Feedback: **Story-Walkthrough in 5 Akten** beim ersten Sichtbarwerden —
(1) Extension über das Toolbar-Icon öffnen, (2) "Raum erstellen" (eigener Pre-Room-
Screen im Popup, `#demo-room-empty`), (3) Invite-Link fliegt animiert vom Popup zum
zweiten Browserfenster (Toast "Raum beigetreten", KoalaPC erscheint in der Peer-Liste,
"IN SYNC"-Chip blendet erst jetzt ein), (4) beide wählen den Video-Tab (Select-Flash im
Popup + Toast am zweiten Fenster), (5) Play für alle → Popup schließt → Pause vom
anderen Tab, Seek mit Nachziehen, Play. Danach voll manuell. Jede Interaktion während
der Story bricht ab und springt via idempotentem `finishDemo()` sofort in den End-
zustand (Raum verbunden, Chip an, Hint an; Popup schließt bei Klicks außerhalb);
der Nutzer-Klick wirkt anschließend normal. 4 neue Locale-Keys (DEMO_NO_ROOM,
DEMO_CREATE_ROOM, DEMO_JOINED, DEMO_TAB_SELECTED) in allen 15 Sprachen.
- [x] Abspiel-Animation: abstrakter **Strichfigur-Kurzfilm** pro Video (SVG: Hügel-
Silhouetten, laufende Figur mit schwingenden Armen/Beinen, hüpfender Ball) — läuft
nur bei `playing`, Pause friert beide Filme im selben Frame ein
(`animation-play-state`), was die Synchronität sofort sichtbar macht.
## Umsetzungsstatus
- [x] `website/template.html`: Hero-Mockup in `.hero-demo-scene` eingebettet (Chip, 2 Tab-
Karten, Verbindungslinie, Launcher, Ghost-Cursor, Hint); Popup-Inhalt unverändert,
nur IDs für Play/Pause/Force-Sync ergänzt.
- [x] `website/style.css`: Demo-Styles mit Container-Queries (cqw + px-Fallbacks),
Mobile-Fallback, `prefers-reduced-motion`-Support.
- [x] `website/app.js`: `initHeroDemo()` — Playback-Uhr (rAF, 8x Zeitraffer), Broadcast-
Logik (Play/Pause/Seek → Peer folgt), manuelle Steuerung, einmaliger Auto-Durchlauf
(Play in Tab A → Seek in Tab B → Pause in Tab B → Popup öffnen/Play/schließen); jede
Interaktion bricht den Durchlauf sofort ab. Auto- und Manuell-Modus nutzen dieselben
Click-Handler. Launcher-Klicks sind vom Karten-Play/Pause entkoppelt (closest-Guard).
- [x] `website/locales/*.json`: 3 neue Keys (`DEMO_SYNC`, `DEMO_DRIFT`, `DEMO_HINT`) in
allen 15 Sprachen.
- [x] `eslint.config.mjs`: `requestAnimationFrame`/`cancelAnimationFrame` zu den Globals.
- [x] Verifiziert im Browser-Preview: Auto-Durchlauf, Drift-Szenario, Chip-Rettungsweg,
Re-Sync, Mobile-Fallback (statisches Popup wie vorher), keine Konsolenfehler,
Lint sauber, Build ohne offene Platzhalter.
- [ ] `.claude/launch.json` zeigt auf einen Session-Scratchpad-Server — vor dem PR prüfen,
ob die Datei ins Repo soll (ggf. löschen oder auf dauerhaften Pfad umstellen).
## Scope / Nicht-Ziele
- Kein Backend, keine echten Videos/Assets, keine neuen npm-Dependencies.
- Kein Umbau des restlichen Landingpage-Contents (Features, Compat-Section, Footer etc.) —
ausschließlich das Hero-Mockup.
- Mobile-Ansicht bekommt **kein** neues Design, bleibt 1:1 der heutige Stand.
+2 -2
View File
@@ -6,7 +6,7 @@
<p align="center">
<a href="https://github.com/Shik3i/KoalaSync/actions/workflows/release.yml"><img src="https://github.com/Shik3i/KoalaSync/actions/workflows/release.yml/badge.svg" alt="Release Status"></a>
<a href="https://github.com/Shik3i/KoalaSync/releases"><img src="https://img.shields.io/badge/Release-v2.5.3-blue?logo=github" alt="GitHub release"></a>
<a href="https://github.com/Shik3i/KoalaSync/releases"><img src="https://img.shields.io/badge/Release-v2.6.0-blue?logo=github" alt="GitHub release"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue" alt="License"></a>
<a href="https://addons.mozilla.org/de/firefox/addon/koalasync/"><img src="https://img.shields.io/badge/Firefox-Download-orange?logo=firefoxbrowser&logoColor=white" alt="Firefox Add-on"></a>
<a href="https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc"><img src="https://img.shields.io/badge/Chrome-Download-blue?logo=googlechrome&logoColor=white" alt="Chrome Extension"></a>
@@ -14,7 +14,7 @@
<p align="center"><i>KoalaSync is a lightweight Browser Extension and Relay Server for synchronized video playback on almost any website with a video element—YouTube, Twitch, Netflix, Emby, Jellyfin, and beyond. Built with a focus on <b>Data Sovereignty</b> and <b>Performance</b>.</i></p>
<p align="center"><a href="docs/CHANGELOG.md"><b>New v2.5.3 Release!</b> — See what's changed</a></p>
<p align="center"><a href="docs/CHANGELOG.md"><b>New v2.6.0 Release!</b> — See what's changed</a></p>
### 🌟 Why KoalaSync?
+2 -2
View File
@@ -16,7 +16,7 @@ Ready-to-paste copy for product listings, launch pages, directory submissions, a
## 2. Three-Sentence Overview
> KoalaSync is a lightweight browser extension that keeps you and your friends perfectly in sync on YouTube, Netflix, Twitch, Prime Video, Jellyfin, Emby, and almost any other site with an HTML5 video player — press play once and everyone stays together. It's built privacy-first: no accounts, no telemetry, and the official relay server runs entirely in volatile RAM with zero persistence, so nothing about your sessions is ever stored. Open source under the MIT license and fully self-hostable with a single Docker command, KoalaSync is a transparent watch-party tool that works everywhere and respects your data sovereignty.
> KoalaSync is a lightweight browser extension that keeps you and your friends perfectly in sync on YouTube, Netflix, Twitch, Prime Video, Jellyfin, Emby, and almost any other site with an HTML5 video player — press play once and everyone stays together. It's built privacy-first: no accounts, no telemetry, and the official relay server runs entirely in volatile RAM with zero persistence, so nothing about your sessions is ever stored. Open source under the MIT license and fully self-hostable with a single Docker Compose command, KoalaSync is a transparent watch-party tool that works everywhere and respects your data sovereignty.
---
@@ -38,7 +38,7 @@ Most watch-party tools fall into one of two traps: they only work on a short all
### Built for people who actually want to read the code
KoalaSync is MIT-licensed open source, built by a solo developer. Audit it, fork it, change it. The extension is dependency-free with a direct Socket.IO wire implementation — no opaque libraries, no framework bloat, no surprise third-party SDKs. Want full sovereignty? Self-host your own relay with a single Docker command and keep all watch-party coordination traffic inside your own infrastructure. The official public relay is there when you don't care, self-hosting is there when you do.
KoalaSync is MIT-licensed open source, built by a solo developer. Audit it, fork it, change it. The extension is dependency-free with a direct Socket.IO wire implementation — no opaque libraries, no framework bloat, no surprise third-party SDKs. Want full sovereignty? Set a unique `SERVER_SALT` in the supplied Compose file, then start your own relay with a single Docker Compose command and keep all watch-party coordination traffic inside your own infrastructure. The official public relay is there when you don't care, self-hosting is there when you do.
### Little touches you'll notice
+4 -4
View File
@@ -1,6 +1,6 @@
KoalaSync: Private Watch Parties for Emby, Jellyfin, Plex, Netflix & YouTube
Tired of counting down "3, 2, 1, Play" over voice chat? KoalaSync keeps you and your friends perfectly in sync. Whether you are streaming from your own self-hosted media server like Emby, Jellyfin or Plex, or watching on a major platform like Netflix, Prime Video or YouTube KoalaSync is designed for smooth, browser-based watch parties.
Tired of counting down "3, 2, 1, Play" over voice chat? KoalaSync keeps you and your friends perfectly in sync. Whether you are streaming from your own self-hosted media server like Emby, Jellyfin or Plex, or watching on a major platform like Netflix, Prime Video or YouTube, KoalaSync is designed for smooth, browser-based watch parties.
✨ CORE FEATURES
@@ -12,7 +12,7 @@ No account required. No tracking. Just create a room, invite your friends, and s
• Smart Binge-Watching: When a new episode loads, KoalaSync automatically pauses the lobby until everyone is ready. No spoilers, no one left behind.
• Smart Audio Compressor: Tired of quiet dialogue and suddenly loud action scenes? Balance whispering, explosions, and music with a single click while you watch.
• One-Click Invites: Send a smart invite link to your friends. When they open it, KoalaSync automatically configures the room so they can join instantly.
• 13 Languages: Enjoy a native experience with a fully translated user interface.
• 15 Languages: Enjoy a native experience in English, German, French, Spanish, Brazilian and European Portuguese, Russian, Italian, Polish, Turkish, Dutch, Japanese, Korean, Simplified Chinese, and Ukrainian.
@@ -33,14 +33,14 @@ KoalaSync is built for private watch parties without unnecessary data collection
3. Share the invite link with your friends.
4. Open your favorite streaming site or media server.
5. Select the active video tab.
6. Press play — everyone stays perfectly in sync.
6. Press play. Everyone stays perfectly in sync.
⚙️ UNDER THE HOOD
KoalaSync is lightweight, transparent, and built with privacy in mind.
• On-Demand Relay: Playback state is synchronized through a custom WebSocket-based relay server. No persistent connection — the relay is only active while you're in a room. No background traffic, no idle connections.
• On-Demand Relay: Playback state is synchronized through a custom WebSocket-based relay server. There is no permanent background connection. The relay connection is maintained only while you're in a room and closes when you leave or automatically after two hours without a selected-video heartbeat.
• No Media Streaming: KoalaSync does not stream, proxy, upload, download, or redistribute any video content. Everyone watches from their own browser on the original website.
• Temporary Room State Only: The relay server only coordinates room state such as play, pause, seek position, active target, nickname, and readiness status.
• Docker Self-Hosting: The relay server can be self-hosted with Docker if you prefer to run your own private instance.
+7 -13
View File
@@ -21,8 +21,8 @@ KoalaSync is a specialized tool for **synchronized video playback** across multi
- `extension/`: Browser Extension (Chrome & Firefox, Manifest V3). Contains background service worker, content scripts, and popup UI.
- `server/`: Node.js Relay Server using Socket.IO (WebSocket-only).
- `website/`: **Landing Page** & Invitation Bridge (Marketing, Tutorials, and Downloads).
- **`build.cjs`**: Zero-dependency static site compiler. Translates `template.html` + `locales/*.json``www/`. Also minifies CSS/JS automatically.
- **`www/` is auto-generated**: Never edit files in `www/` directly. Always edit source files (`template.html`, `style.css`, `app.js`, `lang-init.js`, `locales/*.json`) and run `node website/build.cjs` to regenerate. CSS/JS are output as `.min.*` files — a built-in cleanup step removes stale artifacts on each build.
- **`build.cjs`**: Static site compiler using the repository's build dependencies. Translates `template.html` + `locales/*.json``www/`, generates the sitemap, and minifies HTML/CSS/JS.
- **`www/` is auto-generated**: Never edit files in `www/` directly. Always edit source files (`template.html`, `style.css`, `styles/*.css`, `app.js`, `lang-init.js`, `locales/*.json`) and run `node website/build.cjs` to regenerate. `style.css` is the development manifest; `style.legacy.css` is an unloaded, byte-identical migration reference. Production creates page-specific and render-priority CSS bundles from `styles/*.css`; CSS/JS are output as `.min.*` files and stale generated assets are removed on each build.
- `shared/`: **Single Source of Truth** for protocol constants, event names, blacklist data, and generated usernames.
- `scripts/`: Development utilities (e.g., `build-extension.cjs`).
- `docker-compose.yml`: Root-level orchestration for the relay server.
@@ -64,14 +64,8 @@ The popup UI follows a strict design system. Do not modify these variables or th
- **Font**: System font stack. **MANDATORY**: No external CDNs or Google Fonts to ensure 100% privacy.
- **Popup Width**: Fixed at `320px`.
- **Tab Structure**: Must maintain the visible **Room**, **Sync**, **Settings**, and **Status** tabs. The hidden **Dev** tab is available only for developer diagnostics.
- **CSS Variables**:
| Variable | Value | Purpose |
| :--- | :--- | :--- |
| `--bg` | `#0f172a` | Main background |
| `--card` | `#1e293b` | Form and info cards |
| `--accent` | `#6366f1` | Primary actions and branding |
| `--success` | `#22c55e` | Success states / Online dot |
| `--error` | `#ef4444` | Errors / Offline dot |
- **Appearance modes**: Preserve `system`, `light`, and `dark` behavior and the Eucalyptus, Cyber, and Graphite palettes.
- **CSS variables**: Use the semantic tokens defined in `popup.html` (`--bg`, `--card`, `--accent`, `--text`, `--text-muted`, `--success`, `--warning`, and `--error`). Do not hard-code the retired indigo/slate palette or bypass palette-specific token overrides.
## 7. Non-Negotiables (Core Logic)
The following features are critical and must not be removed or fundamentally altered:
@@ -149,11 +143,11 @@ Before starting any task, committing, or pushing, you **MUST** run `git pull --r
3. Implement the handler in `server/index.js` and `background.js`.
### Making Website Changes
1. Edit source files in `website/` (`template.html`, `style.css`, `app.js`, `lang-init.js`, or `locales/*.json`).
1. Edit source files in `website/` (`template.html`, `style.css`, `styles/*.css`, `app.js`, `lang-init.js`, or `locales/*.json`).
2. Run the compiler: `node website/build.cjs`. This generates the multilingual pages in `www/` and minifies CSS/JS.
3. Verify the output: `node --check website/www/app.min.js && node --check website/www/lang-init.min.js`.
3. Verify the sources and generated contract: `node --check website/app.js`, `node --check website/lang-init.js`, `node scripts/test-website-locales.mjs`, and `node scripts/test-website-theme.mjs`.
4. Test locally: `npx serve website/www` or `python3 -m http.server 8080 -d website/www`.
5. Commit both source changes and the updated `www/` output.
5. Commit the source changes only. `website/www/` is generated and gitignored.
### Testing Locally
1. Run the build script: `node scripts/build-extension.cjs`.
+28 -1
View File
@@ -4,7 +4,34 @@ All notable changes to the KoalaSync browser extension and relay server.
---
## Unreleased
## [v2.6.1] — 2026-07-15
### Fixed
- **Extension: Episode Lobby peer list** — Peer names in the lobby are now rendered as text instead of markup. A peer could previously put HTML in their username and have it rendered in everyone else's popup, which allowed loading remote images (leaking viewer IP addresses) and spoofing the readiness badges. Scripts were already blocked by the extension's content security policy.
### Changed
- **Release checks: AMO validation** — `npm run verify` now runs Mozilla's `addons-linter` against the built Firefox artifact with `--warnings-as-errors`, and ESLint enforces `no-unsanitized`, so upload-blocking issues surface locally instead of at submission time.
---
## [v2.6.0] — 2026-07-15
### Added
- **Extension: Appearance controls** — Added localized system, light, and dark theme options with an early theme initializer to avoid flashes during popup startup.
### Changed
- **Extension: Popup and settings redesign** — Unified controls, status surfaces, colors, icons, badges, and accessibility behavior; settings are now organized into mutually exclusive accordion groups.
### Fixed
- **Extension: Episode Lobby reliability** — Prevented the lobby from remaining stuck in a loading state and stopped episode transitions from triggering on non-episodic media.
- **Extension: Tab-title normalization** — Notification counters such as `(14)`, `[7]`, and `(99+)` are removed reliably without stripping legitimate large numeric titles.
---
## [v2.5.4] — 2026-07-08
### Changed
- **Extension: Refined clutter blacklist** — Removed `localhost` and cloud storage providers (`drive.google.com`, `dropbox.com`, `onedrive.live.com`, `icloud.com`) from the domains blacklist so that local web development servers and tabs hosting video files in cloud storage are no longer hidden under "Hide Clutter Tabs".
---
+3 -2
View File
@@ -18,8 +18,9 @@ KoalaSync is a **privacy-preserving watch-party sync tool**, not a security prod
- **Rooms are ephemeral.** They exist for a few hours and are auto-reaped. There are no
accounts, no persistent storage, no money, and no sensitive content on the relay.
- **The relay is a dumb, stateless message bus.** It forwards play/pause/seek between
peers who *chose* to watch together and joined via an invite link shared out-of-band.
- **The relay is a zero-persistence, in-memory message bus.** It temporarily holds room
and peer state while forwarding play/pause/seek between peers who *chose* to watch
together and joined via an invite link shared out-of-band.
- **Participants are invited.** Anyone in a room was let in. The social contract is
"we're watching a video together," not "mutually distrusting parties."
+9
View File
@@ -1,3 +1,5 @@
import noUnsanitized from "eslint-plugin-no-unsanitized";
export default [
{
ignores: ["coverage/**", "dist/**", "node_modules/**", "scratch/**", "website/www/**"]
@@ -45,7 +47,14 @@ export default [
process: "readonly",
}
},
plugins: {
"no-unsanitized": noUnsanitized
},
rules: {
// Mirrors the AMO validator's "Unsafe assignment to innerHTML" check, so a
// rejection at upload time surfaces here instead.
"no-unsanitized/property": "error",
"no-unsanitized/method": "error",
"no-undef": "error",
"no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_", "caughtErrorsIgnorePattern": "^_" }],
"no-unreachable": "error",
+16
View File
@@ -18,6 +18,14 @@
# # Clean URLs support (resolves /join to join.html, etc.)
# try_files {path} {path}.html {path}/
# file_server
#
# # Serve the themed 404 page for unknown URLs (without this block,
# # Caddy returns an empty 404 response)
# handle_errors {
# @notfound expression {err.status_code} == 404
# rewrite @notfound /404.html
# file_server
# }
# }
#
# syncserver.koalastuff.net {
@@ -57,6 +65,14 @@ sync.koalastuff.net {
try_files {path} {path}.html {path}/
file_server
# Serve the themed 404 page for unknown URLs (without this block,
# Caddy returns an empty 404 response)
handle_errors {
@notfound expression {err.status_code} == 404
rewrite @notfound /404.html
file_server
}
# Static Caching for high-performance PageSpeed (1 year with validation)
@static {
file
+54 -17
View File
@@ -1,13 +1,46 @@
:root {
--bg: #0f172a;
--card: #1e293b;
--panel: #172033;
--accent: #6366f1;
--accent-hover: #818cf8;
--text: #f8fafc;
--text-muted: #94a3b8;
--border: #334155;
/* KoalaSync nature system: forest neutrals, eucalyptus brand, warm supporting accents. */
--bg-base: oklch(0.23 0.028 155);
--surface: oklch(0.30 0.035 150);
--surface-deep: oklch(0.205 0.025 155);
--surface-alt: oklch(0.265 0.032 150);
--border-soft: oklch(0.88 0.025 145 / 0.09);
--border-strong: oklch(0.39 0.038 145);
--text-primary: oklch(0.96 0.01 90);
--text-secondary: oklch(0.78 0.02 90);
--accent-green: oklch(0.73 0.13 155);
--accent-green-hover: oklch(0.79 0.12 155);
--accent-terracotta: oklch(0.62 0.14 45);
--success-green: oklch(0.72 0.14 135);
--warning-amber: oklch(0.76 0.14 80);
--danger: oklch(0.55 0.15 25);
--text-on-green: oklch(0.14 0.02 90);
--bg: var(--bg-base);
--card: var(--surface);
--panel: var(--surface-alt);
--accent: var(--accent-green);
--accent-hover: var(--accent-green-hover);
--text: var(--text-primary);
--text-muted: var(--text-secondary);
--border: var(--border-strong);
--radius: 8px;
color-scheme: dark;
}
html.theme-light {
--bg-base: oklch(0.965 0.012 105);
--surface: oklch(0.995 0.006 100);
--surface-deep: oklch(0.935 0.018 110);
--surface-alt: oklch(0.91 0.022 115);
--border-soft: oklch(0.28 0.035 140 / 0.10);
--border-strong: oklch(0.73 0.035 125);
--text-primary: oklch(0.21 0.03 140);
--text-secondary: oklch(0.43 0.03 135);
--accent-green: oklch(0.52 0.13 155);
--accent-green-hover: oklch(0.45 0.12 155);
--text-on-green: oklch(0.98 0.005 100);
color-scheme: light;
}
* {
@@ -55,7 +88,7 @@ body {
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
letter-spacing: 0.04em;
}
h1,
@@ -83,6 +116,10 @@ h2 {
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}
html.theme-light .panel {
box-shadow: 0 12px 30px oklch(0.22 0.035 140 / 0.09);
}
.muted-panel {
color: var(--text-muted);
}
@@ -101,7 +138,7 @@ h2 {
color: var(--text-muted);
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.01em;
}
.preset-group {
@@ -125,12 +162,12 @@ h2 {
transition: border-color 0.2s, box-shadow 0.2s;
}
.preset-card:hover {
border-color: rgba(99, 102, 241, 0.4);
border-color: color-mix(in oklch, var(--accent), transparent 60%);
}
.preset-card:has(input:checked) {
border-color: var(--accent);
box-shadow: 0 0 0 1px rgba(99, 102, 241, 0.35);
box-shadow: 0 0 0 1px color-mix(in oklch, var(--accent), transparent 65%);
}
.preset-card input {
@@ -141,8 +178,8 @@ h2 {
display: grid;
gap: 12px;
padding: 16px;
background: rgba(15, 23, 42, 0.58);
border: 1px solid rgba(148, 163, 184, 0.16);
background: var(--surface-deep);
border: 1px solid var(--border-soft);
border-radius: var(--radius);
transition: opacity 0.3s;
}
@@ -158,7 +195,7 @@ h2 {
color: var(--text-muted);
font-size: 11px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.01em;
}
input[type="range"] {
@@ -204,7 +241,7 @@ input[type="number"]:focus {
position: absolute;
cursor: pointer;
inset: 0;
background-color: #334155;
background-color: var(--border-strong);
transition: .3s;
border-radius: 22px;
}
@@ -216,7 +253,7 @@ input[type="number"]:focus {
width: 16px;
left: 3px;
bottom: 3px;
background-color: #94a3b8;
background-color: var(--text-secondary);
transition: .3s;
border-radius: 50%;
}
+1
View File
@@ -3,6 +3,7 @@
<head>
<meta charset="utf-8">
<title>KoalaSync Audio Settings</title>
<script src="theme-init.js"></script>
<link rel="stylesheet" href="audio-options.css">
</head>
<body>
+26 -4
View File
@@ -1,7 +1,7 @@
import { EVENTS, CONTROL_MODES, CAPABILITIES, PROTOCOL_VERSION, OFFICIAL_SERVER_URL, OFFICIAL_SERVER_TOKEN, EPISODE_LOBBY_TIMEOUT, FORCE_SYNC_TIMEOUT, HEARTBEAT_INTERVAL } from './shared/constants.js';
import { generateUsername } from './shared/names.js';
import { loadLocale, getMessage, getSystemLanguage } from './i18n.js';
import { sameEpisode } from './episode-utils.js';
import { sameEpisode, extractEpisodeId } from './episode-utils.js';
import { applyTitlePrivacyToPayload, sanitizeSharedTitle, sanitizeTabTitle, normalizeSendTabTitle, normalizeTitlePrivacyMode } from './title-privacy.js';
import { initTabManager } from './modules/tab-manager.js';
import './page-api-seek-overrides.js';
@@ -790,13 +790,13 @@ function updateBadgeStatus() {
if (status === 'reconnecting') {
chrome.action.setBadgeText({ text: '...' });
chrome.action.setBadgeBackgroundColor({ color: '#f59e0b' });
chrome.action.setBadgeBackgroundColor({ color: '#c96736' });
} else if (status === 'connecting') {
chrome.action.setBadgeText({ text: '...' });
chrome.action.setBadgeBackgroundColor({ color: '#fbbf24' });
chrome.action.setBadgeBackgroundColor({ color: '#de7949' });
} else if (status === 'connected' && currentRoom && currentTabId) {
chrome.action.setBadgeText({ text: 'ON' });
chrome.action.setBadgeBackgroundColor({ color: '#22c55e' });
chrome.action.setBadgeBackgroundColor({ color: '#56ae6c' });
} else {
chrome.action.setBadgeText({ text: '' });
}
@@ -1325,6 +1325,9 @@ function handleServerEvent(event, data) {
}
if (storageInitialized) chrome.storage.session.set({ currentRoom });
chrome.runtime.sendMessage({ type: 'PEER_UPDATE', peers: currentRoom.peers }).catch(() => {});
if (episodeLobby) {
checkEpisodeLobbyCompletion();
}
}
}
}
@@ -2476,6 +2479,11 @@ async function handleAsyncMessage(message, sender, sendResponse) {
}
const newTitle = message.payload && message.payload.newTitle;
if (newTitle && extractEpisodeId(newTitle) === null) {
addLog(`Episode change detected ("${newTitle}") but no episode ID was found; ignoring.`, 'info');
sendResponse({ status: 'not_an_episode' });
return;
}
if (!newTitle) {
sendResponse({ status: 'no_title' });
return;
@@ -2566,6 +2574,13 @@ async function handleAsyncMessage(message, sender, sendResponse) {
sendResponse({ status: 'lobby_created' });
} else if (message.type === 'EPISODE_READY_LOCAL') {
if (sender.tab) {
const senderTabId = sender.tab.id;
if (!currentTabId || currentTabId !== senderTabId) {
sendResponse({ status: 'ignored_unselected_tab' });
return;
}
}
// Content script confirmed it loaded the lobby episode
if (episodeLobby && message.payload && sameEpisode(message.payload.title, episodeLobby.expectedTitle)) {
if (!episodeLobby.readyPeers.includes(peerId)) {
@@ -2604,6 +2619,13 @@ async function handleAsyncMessage(message, sender, sendResponse) {
}
sendResponse({ status: 'ok' });
} else if (message.type === 'CONTENT_BOOT') {
if (sender.tab) {
const senderTabId = sender.tab.id;
if (!currentTabId || currentTabId !== senderTabId) {
sendResponse({ status: 'ignored_unselected_tab' });
return;
}
}
// Content script re-injected, check if there's an active lobby
if (episodeLobby) {
sendResponse({ lobbyActive: true, expectedTitle: episodeLobby.expectedTitle });
+12 -7
View File
@@ -424,13 +424,13 @@
if (video.seeking) return 'involuntary';
if (Date.now() < hcmBufferingUntil) return 'involuntary';
if (Date.now() < hcmBufferingUntil) return 'involuntary';
if (Date.now() < visibilityGraceUntil) return 'involuntary';
if (Date.now() - hcmLastUserGestureAt > HCM_USER_GESTURE_MS) return 'involuntary';
return 'deliberate';
return 'deliberate';
}
@@ -494,7 +494,7 @@
if (target && target.playbackState === 'paused') {
tryMediaAction(EVENTS.PAUSE);
tryMediaAction(EVENTS.PAUSE);
} else if (target && target.playbackState === 'playing') {
@@ -758,7 +758,8 @@
let settled = false;
// Re-query the host's current position on click instead of using the
// Re-query the host's current position on click instead of using the
// potentially stale target captured at HOST_BLOCKED time (M-1).
const stay = () => {
@@ -798,7 +799,11 @@
chrome.runtime.sendMessage({ type: 'HCM_DESYNC_STATE', desynced: true }).catch(() => {});
hcmShowBadge();
hcmShowBadge();
}
function hcmExitDesync() {
const wasDesynced = hcmDesynced;
+5
View File
@@ -12,6 +12,9 @@ let currentLanguage = null;
*/
export async function loadLocale(langCode) {
const resolvedLang = SUPPORTED_LANGUAGES.includes(langCode) ? langCode : DEFAULT_LANGUAGE;
if (typeof document !== 'undefined') {
document.documentElement.lang = resolvedLang;
}
if (currentLanguage === resolvedLang && Object.keys(activeDictionary).length > 0) {
return;
@@ -90,6 +93,8 @@ export function getMessage(key, placeholders = null) {
* Performs dynamic DOM replacements for elements carrying data-i18n attributes.
*/
export function translateDOM() {
if (typeof document === 'undefined') return;
// 1. Text Content
document.querySelectorAll('[data-i18n]').forEach(el => {
const key = el.getAttribute('data-i18n');
+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path d="M3 2.5h4v11H3zm6 0h4v11H9z"/>
</svg>

After

Width:  |  Height:  |  Size: 109 B

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path d="M4 2.6v10.8L13 8z"/>
</svg>

After

Width:  |  Height:  |  Size: 100 B

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path d="M13.4 5.5A5.8 5.8 0 0 0 3 4.2L1.7 2.9v4.4h4.4L4.4 5.6a4 4 0 0 1 7.2.8zM2.6 10.5A5.8 5.8 0 0 0 13 11.8l1.3 1.3V8.7H9.9l1.7 1.7a4 4 0 0 1-7.2-.8z"/>
</svg>

After

Width:  |  Height:  |  Size: 226 B

+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Fernsteuerung",
"BTN_COPY_INVITE": "📋 Einladungslink",
"BTN_COPY_INVITE_TOOLTIP": "Einladungslink kopieren",
"BTN_PLAY": "Abspielen",
"BTN_PLAY": "Abspielen",
"BTN_PLAY_TOOLTIP": "Sende einen Play-Befehl an alle",
"BTN_PAUSE": "Pause",
"BTN_PAUSE": "Pause",
"BTN_PAUSE_TOOLTIP": "Sende einen Pause-Befehl an alle",
"BTN_SYNC": "⚡ SYNC",
"BTN_SYNC": "Sync",
"BTN_SYNC_TOOLTIP": "Erzwinge die Synchronisation aller Teilnehmer",
"OPTION_JUMP_TO_OTHERS": "Zu anderen springen",
"OPTION_JUMP_TO_ME": "Zu mir springen",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Wendet Audioeffekte wie Kompression auf die Videowiedergabe an",
"AUDIO_OPEN_SETTINGS": "Öffnen",
"NEW_FEATURE_AUDIO": "Neu: Audio-Verarbeitung — probiere den Kompressor aus!",
"NEW_FEATURE_THEME": "Neu: Themes — wechsle zum klassischen Look oder minimalem Graphit.",
"AUDIO_BACK": "← Zurück",
"AUDIO_PAGE_TITLE": "Audio-Einstellungen",
"AUDIO_MASTER_TOGGLE": "Audio-Verarbeitung",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Tab-Titel senden",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Sendet den Titel des ausgewählten Browser-Tabs an den Raum.",
"LABEL_MEDIA_TITLE_PRIVACY": "Medientitel",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Lege fest, wie Medientitel an den Raum gesendet werden."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Lege fest, wie Medientitel an den Raum gesendet werden.",
"LABEL_SETTINGS_GROUP_PROFILE": "Profil & Aussehen",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Ändere deinen Benutzernamen, dein Design und deine Spracheinstellungen.",
"LABEL_SETTINGS_GROUP_SYNC": "Wiedergabe & Sync",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Passe Wiedergabe-, Benachrichtigungs- und Audioeinstellungen an."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Remote Control",
"BTN_COPY_INVITE": "📋 Invite Link",
"BTN_COPY_INVITE_TOOLTIP": "Copy Invite Link",
"BTN_PLAY": "Play",
"BTN_PLAY": "Play",
"BTN_PLAY_TOOLTIP": "Send a Play command to everyone",
"BTN_PAUSE": "Pause",
"BTN_PAUSE": "Pause",
"BTN_PAUSE_TOOLTIP": "Send a Pause command to everyone",
"BTN_SYNC": "⚡ SYNC",
"BTN_SYNC": "Sync",
"BTN_SYNC_TOOLTIP": "Force all users to sync up",
"OPTION_JUMP_TO_OTHERS": "Jump to Others",
"OPTION_JUMP_TO_ME": "Jump to Me",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Apply audio effects like compression to video playback",
"AUDIO_OPEN_SETTINGS": "Open",
"NEW_FEATURE_AUDIO": "New: Audio Processing — try the compressor!",
"NEW_FEATURE_THEME": "New: Themes — switch to the classic look or minimal graphite.",
"AUDIO_BACK": "← Back",
"AUDIO_PAGE_TITLE": "Audio Settings",
"AUDIO_MASTER_TOGGLE": "Audio Processing",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Send tab title",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Send the selected browser tab title to the room.",
"LABEL_MEDIA_TITLE_PRIVACY": "Media title",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Choose how media titles are sent to the room."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Choose how media titles are sent to the room.",
"LABEL_SETTINGS_GROUP_PROFILE": "Profile & Appearance",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Change your username, theme, and language preferences.",
"LABEL_SETTINGS_GROUP_SYNC": "Playback & Sync",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Customize playback, notifications, and audio preferences."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Control remoto",
"BTN_COPY_INVITE": "📋 Enlace de invitación",
"BTN_COPY_INVITE_TOOLTIP": "Copiar enlace de invitación",
"BTN_PLAY": "Reproducir",
"BTN_PLAY": "Reproducir",
"BTN_PLAY_TOOLTIP": "Enviar un comando de reproducción a todos",
"BTN_PAUSE": "Pausar",
"BTN_PAUSE": "Pausar",
"BTN_PAUSE_TOOLTIP": "Enviar un comando de pausa a todos",
"BTN_SYNC": "⚡ SYNC",
"BTN_SYNC": "Sync",
"BTN_SYNC_TOOLTIP": "Forzar la sincronización de todos los usuarios",
"OPTION_JUMP_TO_OTHERS": "Ir a la posición de otros",
"OPTION_JUMP_TO_ME": "Traerlos a mi posición",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Aplica efectos de audio como compresión a la reproducción de video",
"AUDIO_OPEN_SETTINGS": "Abrir",
"NEW_FEATURE_AUDIO": "Nuevo: Procesamiento de audio — ¡prueba el compresor!",
"NEW_FEATURE_THEME": "Nuevo: Temas — cambia al aspecto clásico o al grafito minimalista.",
"AUDIO_BACK": "← Volver",
"AUDIO_PAGE_TITLE": "Configuración de audio",
"AUDIO_MASTER_TOGGLE": "Procesamiento de audio",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Enviar título de pestaña",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Envía a la sala el título de la pestaña del navegador seleccionada.",
"LABEL_MEDIA_TITLE_PRIVACY": "Título multimedia",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Elige cómo se envían los títulos multimedia a la sala."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Elige cómo se envían los títulos multimedia a la sala.",
"LABEL_SETTINGS_GROUP_PROFILE": "Perfil y Apariencia",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Cambia tu nombre de usuario, tema y preferencias de idioma.",
"LABEL_SETTINGS_GROUP_SYNC": "Reproducción y Sincronización",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Personaliza la reproducción, las notificaciones y las preferencias de audio."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Contrôle à distance",
"BTN_COPY_INVITE": "📋 Lien d'invitation",
"BTN_COPY_INVITE_TOOLTIP": "Copier le lien d'invitation",
"BTN_PLAY": "Lecture",
"BTN_PLAY": "Lecture",
"BTN_PLAY_TOOLTIP": "Envoyer une commande Lecture à tout le monde",
"BTN_PAUSE": "Pause",
"BTN_PAUSE": "Pause",
"BTN_PAUSE_TOOLTIP": "Envoyer une commande Pause à tout le monde",
"BTN_SYNC": "⚡ SYNC",
"BTN_SYNC": "Sync",
"BTN_SYNC_TOOLTIP": "Forcer tous les utilisateurs à se synchroniser",
"OPTION_JUMP_TO_OTHERS": "Rejoindre les autres",
"OPTION_JUMP_TO_ME": "Les amener à moi",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Applique des effets audio comme la compression à la lecture vidéo",
"AUDIO_OPEN_SETTINGS": "Ouvrir",
"NEW_FEATURE_AUDIO": "Nouveau : Traitement audio — essayez le compresseur !",
"NEW_FEATURE_THEME": "Nouveau : Thèmes — passez au look classique ou au graphite minimal.",
"AUDIO_BACK": "← Retour",
"AUDIO_PAGE_TITLE": "Paramètres audio",
"AUDIO_MASTER_TOGGLE": "Traitement audio",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Envoyer le titre de longlet",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Envoie au salon le titre de longlet de navigateur sélectionné.",
"LABEL_MEDIA_TITLE_PRIVACY": "Titre du média",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Choisissez comment les titres des médias sont envoyés au salon."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Choisissez comment les titres des médias sont envoyés au salon.",
"LABEL_SETTINGS_GROUP_PROFILE": "Profil & Apparence",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Modifiez votre nom d'utilisateur, votre thème et vos préférences linguistiques.",
"LABEL_SETTINGS_GROUP_SYNC": "Lecture & Sync",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Personnalisez la lecture, les notifications et les préférences audio."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Telecomando",
"BTN_COPY_INVITE": "📋 Link di Invito",
"BTN_COPY_INVITE_TOOLTIP": "Copia il link di invito",
"BTN_PLAY": "Riproduci",
"BTN_PLAY": "Riproduci",
"BTN_PLAY_TOOLTIP": "Avvia la riproduzione per tutti",
"BTN_PAUSE": "Pausa",
"BTN_PAUSE": "Pausa",
"BTN_PAUSE_TOOLTIP": "Metti in pausa per tutti",
"BTN_SYNC": "⚡ SINCRO",
"BTN_SYNC": "Sincro",
"BTN_SYNC_TOOLTIP": "Forza la sincronizzazione per tutti",
"OPTION_JUMP_TO_OTHERS": "Vai alla posizione degli altri",
"OPTION_JUMP_TO_ME": "Portali alla mia posizione",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Applica effetti sonori (come il compressore) ai video",
"AUDIO_OPEN_SETTINGS": "Apri",
"NEW_FEATURE_AUDIO": "Novità: Elaborazione Audio — prova il compressore!",
"NEW_FEATURE_THEME": "Nuovo: Temi — passa all'aspetto classico o al grafite minimale.",
"AUDIO_BACK": "← Indietro",
"AUDIO_PAGE_TITLE": "Impostazioni Audio",
"AUDIO_MASTER_TOGGLE": "Elaborazione Audio",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Invia titolo scheda",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Invia alla stanza il titolo della scheda del browser selezionata.",
"LABEL_MEDIA_TITLE_PRIVACY": "Titolo multimediale",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Scegli come inviare alla stanza i titoli multimediali."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Scegli come inviare alla stanza i titoli multimediali.",
"LABEL_SETTINGS_GROUP_PROFILE": "Profilo & Aspetto",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Modifica il tuo nome utente, tema e preferenze di lingua.",
"LABEL_SETTINGS_GROUP_SYNC": "Riproduzione & Sync",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Personalizza la riproduzione, le notifiche e le preferenze audio."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "リモートコントロール",
"BTN_COPY_INVITE": "📋 招待リンク",
"BTN_COPY_INVITE_TOOLTIP": "招待リンクをコピー",
"BTN_PLAY": "再生",
"BTN_PLAY": "再生",
"BTN_PLAY_TOOLTIP": "全員に再生コマンドを送信",
"BTN_PAUSE": "一時停止",
"BTN_PAUSE": "一時停止",
"BTN_PAUSE_TOOLTIP": "全員に一時停止コマンドを送信",
"BTN_SYNC": "同期",
"BTN_SYNC": "同期",
"BTN_SYNC_TOOLTIP": "すべてのユーザーを強制的に同期",
"OPTION_JUMP_TO_OTHERS": "他の人に合わせる",
"OPTION_JUMP_TO_ME": "自分に合わせる",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "動画再生に圧縮などのオーディオエフェクトを適用します",
"AUDIO_OPEN_SETTINGS": "開く",
"NEW_FEATURE_AUDIO": "新機能: オーディオ処理 — コンプレッサーを試してみよう!",
"NEW_FEATURE_THEME": "新機能:テーマ — クラシックな外観やミニマルなグラファイトに切り替え。",
"AUDIO_BACK": "← 戻る",
"AUDIO_PAGE_TITLE": "オーディオ設定",
"AUDIO_MASTER_TOGGLE": "オーディオ処理",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "タブタイトルを送信",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "選択中のブラウザータブのタイトルをルームに送信します。",
"LABEL_MEDIA_TITLE_PRIVACY": "メディアタイトル",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "メディアタイトルをルームに送信する方法を選択します。"
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "メディアタイトルをルームに送信する方法を選択します。",
"LABEL_SETTINGS_GROUP_PROFILE": "プロフィールと外観",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "ユーザー名、テーマ、言語設定を変更します。",
"LABEL_SETTINGS_GROUP_SYNC": "再生と同期",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "再生、通知、オーディオ設定をカスタマイズします。"
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "원격 제어",
"BTN_COPY_INVITE": "📋 초대 링크",
"BTN_COPY_INVITE_TOOLTIP": "초대 링크 복사",
"BTN_PLAY": "재생",
"BTN_PLAY": "재생",
"BTN_PLAY_TOOLTIP": "모든 사람에게 재생 명령 전송",
"BTN_PAUSE": "일시정지",
"BTN_PAUSE": "일시정지",
"BTN_PAUSE_TOOLTIP": "모든 사람에게 일시정지 명령 전송",
"BTN_SYNC": "동기화",
"BTN_SYNC": "동기화",
"BTN_SYNC_TOOLTIP": "모든 사용자의 강제 동기화",
"OPTION_JUMP_TO_OTHERS": "다른 사람에게 이동",
"OPTION_JUMP_TO_ME": "나에게 이동",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "비디오 재생에 압축과 같은 오디오 효과를 적용합니다",
"AUDIO_OPEN_SETTINGS": "열기",
"NEW_FEATURE_AUDIO": "신규: 오디오 처리 — 컴프레서를 사용해보세요!",
"NEW_FEATURE_THEME": "신규: 테마 — 클래식 룩이나 미니멀 그래파이트로 전환하세요.",
"AUDIO_BACK": "← 뒤로",
"AUDIO_PAGE_TITLE": "오디오 설정",
"AUDIO_MASTER_TOGGLE": "오디오 처리",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "탭 제목 보내기",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "선택한 브라우저 탭 제목을 방에 보냅니다.",
"LABEL_MEDIA_TITLE_PRIVACY": "미디어 제목",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "미디어 제목을 방에 보내는 방식을 선택합니다."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "미디어 제목을 방에 보내는 방식을 선택합니다.",
"LABEL_SETTINGS_GROUP_PROFILE": "프로필 및 테마",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "사용자 이름, 테마 및 언어 설정을 변경합니다.",
"LABEL_SETTINGS_GROUP_SYNC": "재생 및 동기화",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "재생, 알림 및 오디오 설정을 맞춤설정합니다."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Afstandsbediening",
"BTN_COPY_INVITE": "📋 Uitnodigingslink",
"BTN_COPY_INVITE_TOOLTIP": "Uitnodigingslink kopiëren",
"BTN_PLAY": "Afspelen",
"BTN_PLAY": "Afspelen",
"BTN_PLAY_TOOLTIP": "Stuur een afspeelopdracht naar iedereen",
"BTN_PAUSE": "Pauzeren",
"BTN_PAUSE": "Pauzeren",
"BTN_PAUSE_TOOLTIP": "Stuur een pauzeeropdracht naar iedereen",
"BTN_SYNC": "⚡ SYNC",
"BTN_SYNC": "Sync",
"BTN_SYNC_TOOLTIP": "Dwing alle gebruikers om te synchroniseren",
"OPTION_JUMP_TO_OTHERS": "Spring naar anderen",
"OPTION_JUMP_TO_ME": "Spring naar mij",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Past audio-effecten zoals compressie toe op video-afspelen",
"AUDIO_OPEN_SETTINGS": "Openen",
"NEW_FEATURE_AUDIO": "Nieuw: Audioverwerking — probeer de compressor!",
"NEW_FEATURE_THEME": "Nieuw: Thema's — schakel naar de klassieke look of minimaal grafiet.",
"AUDIO_BACK": "← Terug",
"AUDIO_PAGE_TITLE": "Audio-instellingen",
"AUDIO_MASTER_TOGGLE": "Audioverwerking",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Tabtitel verzenden",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Stuurt de titel van het geselecteerde browsertabblad naar de kamer.",
"LABEL_MEDIA_TITLE_PRIVACY": "Mediatitel",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Kies hoe mediatitels naar de kamer worden gestuurd."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Kies hoe mediatitels naar de kamer worden gestuurd.",
"LABEL_SETTINGS_GROUP_PROFILE": "Profiel & Weergave",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Wijzig uw gebruikersnaam, thema en taalvoorkeuren.",
"LABEL_SETTINGS_GROUP_SYNC": "Afspelen & Sync",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Pas afspelen, meldingen en audiovoorkeuren aan."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Zdalne sterowanie",
"BTN_COPY_INVITE": "📋 Link do zaproszenia",
"BTN_COPY_INVITE_TOOLTIP": "Kopiuj link zaproszenia",
"BTN_PLAY": "Odtwórz",
"BTN_PLAY": "Odtwórz",
"BTN_PLAY_TOOLTIP": "Wyślij polecenie odtwarzania do wszystkich",
"BTN_PAUSE": "Pauza",
"BTN_PAUSE": "Pauza",
"BTN_PAUSE_TOOLTIP": "Wyślij polecenie pauzy do wszystkich",
"BTN_SYNC": "⚡ SYNC",
"BTN_SYNC": "Sync",
"BTN_SYNC_TOOLTIP": "Wymuś synchronizację wszystkich użytkowników",
"OPTION_JUMP_TO_OTHERS": "Skocz do innych",
"OPTION_JUMP_TO_ME": "Skocz do mnie",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Stosuje efekty dźwiękowe, takie jak kompresja, do odtwarzania wideo",
"AUDIO_OPEN_SETTINGS": "Otwórz",
"NEW_FEATURE_AUDIO": "Nowość: Przetwarzanie dźwięku — wypróbuj kompresor!",
"NEW_FEATURE_THEME": "Nowość: Motywy — przełącz na klasyczny wygląd lub minimalny grafit.",
"AUDIO_BACK": "← Wstecz",
"AUDIO_PAGE_TITLE": "Ustawienia dźwięku",
"AUDIO_MASTER_TOGGLE": "Przetwarzanie dźwięku",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Wysyłaj tytuł karty",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Wysyła do pokoju tytuł wybranej karty przeglądarki.",
"LABEL_MEDIA_TITLE_PRIVACY": "Tytuł multimediów",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Wybierz, jak tytuły multimediów są wysyłane do pokoju."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Wybierz, jak tytuły multimediów są wysyłane do pokoju.",
"LABEL_SETTINGS_GROUP_PROFILE": "Profil i Wygląd",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Zmień swoją nazwę użytkownika, motyw i preferencje językowe.",
"LABEL_SETTINGS_GROUP_SYNC": "Odtwarzanie i Sync",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Dostosuj odtwarzanie, powiadomienia i preferencje audio."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Controle remoto",
"BTN_COPY_INVITE": "📋 Link de convite",
"BTN_COPY_INVITE_TOOLTIP": "Copiar link de convite",
"BTN_PLAY": "Reproduzir",
"BTN_PLAY": "Reproduzir",
"BTN_PLAY_TOOLTIP": "Iniciar a reprodução para todos",
"BTN_PAUSE": "Pausar",
"BTN_PAUSE": "Pausar",
"BTN_PAUSE_TOOLTIP": "Pausar o vídeo para todos",
"BTN_SYNC": "⚡ SINCRO",
"BTN_SYNC": "Sincro",
"BTN_SYNC_TOOLTIP": "Forçar todos os usuários a sincronizar",
"OPTION_JUMP_TO_OTHERS": "Ir para a posição dos outros",
"OPTION_JUMP_TO_ME": "Trazer para a minha posição",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Aplica efeitos de áudio (como compressão) aos vídeos",
"AUDIO_OPEN_SETTINGS": "Abrir",
"NEW_FEATURE_AUDIO": "Novo: Processamento de áudio — experimente o compressor!",
"NEW_FEATURE_THEME": "Novo: Temas — mude para o visual clássico ou grafite minimalista.",
"AUDIO_BACK": "← Voltar",
"AUDIO_PAGE_TITLE": "Configurações de áudio",
"AUDIO_MASTER_TOGGLE": "Processamento de áudio",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Enviar título da aba",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Envia para a sala o título da aba selecionada do navegador.",
"LABEL_MEDIA_TITLE_PRIVACY": "Título da mídia",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Escolha como os títulos de mídia são enviados para a sala."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Escolha como os títulos de mídia são enviados para a sala.",
"LABEL_SETTINGS_GROUP_PROFILE": "Perfil e Aparência",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Altere o seu nome de usuário, tema e preferências de idioma.",
"LABEL_SETTINGS_GROUP_SYNC": "Reprodução e Sincronização",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Personalize a reprodução, as notificações e as preferências de áudio."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Controlo Remoto",
"BTN_COPY_INVITE": "📋 Link de Convite",
"BTN_COPY_INVITE_TOOLTIP": "Copiar Link de Convite",
"BTN_PLAY": "Reproduzir",
"BTN_PLAY": "Reproduzir",
"BTN_PLAY_TOOLTIP": "Iniciar a reprodução para todos",
"BTN_PAUSE": "Pausa",
"BTN_PAUSE": "Pausa",
"BTN_PAUSE_TOOLTIP": "Pausar o vídeo para todos",
"BTN_SYNC": "⚡ SINCRO",
"BTN_SYNC": "Sincro",
"BTN_SYNC_TOOLTIP": "Forçar sincronização de todos os utilizadores",
"OPTION_JUMP_TO_OTHERS": "Ir para a posição dos outros",
"OPTION_JUMP_TO_ME": "Trazer para a minha posição",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Aplica efeitos de áudio (como compressão) aos vídeos",
"AUDIO_OPEN_SETTINGS": "Abrir",
"NEW_FEATURE_AUDIO": "Novo: Processamento de áudio — experimente o compressor!",
"NEW_FEATURE_THEME": "Novo: Temas — mude para o visual clássico ou grafite minimalista.",
"AUDIO_BACK": "← Voltar",
"AUDIO_PAGE_TITLE": "Configurações de Áudio",
"AUDIO_MASTER_TOGGLE": "Processamento de Áudio",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Enviar título do separador",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Envia para a sala o título do separador do navegador selecionado.",
"LABEL_MEDIA_TITLE_PRIVACY": "Título multimédia",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Escolhe como os títulos multimédia são enviados para a sala."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Escolhe como os títulos multimédia são enviados para a sala.",
"LABEL_SETTINGS_GROUP_PROFILE": "Perfil e Aparência",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Altere o seu nome de utilizador, tema e preferências de idioma.",
"LABEL_SETTINGS_GROUP_SYNC": "Reprodução e Sincronização",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Personalize a reprodução, as notificações e as preferências de áudio."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Дистанционное управление",
"BTN_COPY_INVITE": "📋 Ссылка",
"BTN_COPY_INVITE_TOOLTIP": "Копировать ссылку-приглашение",
"BTN_PLAY": "Запуск",
"BTN_PLAY": "Запуск",
"BTN_PLAY_TOOLTIP": "Отправить команду воспроизведения всем",
"BTN_PAUSE": "Пауза",
"BTN_PAUSE": "Пауза",
"BTN_PAUSE_TOOLTIP": "Отправить команду паузы всем",
"BTN_SYNC": "⚡ СИНХРО",
"BTN_SYNC": "Синхро",
"BTN_SYNC_TOOLTIP": "Принудительно синхронизировать всех участников",
"OPTION_JUMP_TO_OTHERS": "Перейти к другим",
"OPTION_JUMP_TO_ME": "Синхронизировать по мне",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Применяет аудиоэффекты, такие как сжатие, к воспроизведению видео",
"AUDIO_OPEN_SETTINGS": "Открыть",
"NEW_FEATURE_AUDIO": "Новое: Обработка звука — попробуйте компрессор!",
"NEW_FEATURE_THEME": "Новое: Темы — переключитесь на классический вид или минимальный графит.",
"AUDIO_BACK": "← Назад",
"AUDIO_PAGE_TITLE": "Настройки звука",
"AUDIO_MASTER_TOGGLE": "Обработка звука",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Отправлять название вкладки",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Отправляет в комнату название выбранной вкладки браузера.",
"LABEL_MEDIA_TITLE_PRIVACY": "Название медиа",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Выберите, как названия медиа отправляются в комнату."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Выберите, как названия медиа отправляются в комнату.",
"LABEL_SETTINGS_GROUP_PROFILE": "Профиль и Оформление",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Измените имя пользователя, тему и настройки языка.",
"LABEL_SETTINGS_GROUP_SYNC": "Воспроизведение и Синхронизация",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Настройте воспроизведение, уведомления и параметры звука."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Uzaktan Kumanda",
"BTN_COPY_INVITE": "📋 Davet Linki",
"BTN_COPY_INVITE_TOOLTIP": "Davet Linkini Kopyala",
"BTN_PLAY": "Oynat",
"BTN_PLAY": "Oynat",
"BTN_PLAY_TOOLTIP": "Herkese Oynat komutu gönder",
"BTN_PAUSE": "Duraklat",
"BTN_PAUSE": "Duraklat",
"BTN_PAUSE_TOOLTIP": "Herkese Duraklat komutu gönder",
"BTN_SYNC": "⚡ SYNC",
"BTN_SYNC": "Sync",
"BTN_SYNC_TOOLTIP": "Tüm kullanıcıları senkronize etmeye zorla",
"OPTION_JUMP_TO_OTHERS": "Diğerlerine Atla",
"OPTION_JUMP_TO_ME": "Bana Atla",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Video oynatımına sıkıştırma gibi ses efektleri uygular",
"AUDIO_OPEN_SETTINGS": "Aç",
"NEW_FEATURE_AUDIO": "Yeni: Ses işleme — kompresörü deneyin!",
"NEW_FEATURE_THEME": "Yeni: Temalar — klasik görünüme veya minimal grafite geçin.",
"AUDIO_BACK": "← Geri",
"AUDIO_PAGE_TITLE": "Ses ayarları",
"AUDIO_MASTER_TOGGLE": "Ses işleme",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Sekme başlığını gönder",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Seçili tarayıcı sekmesinin başlığını odaya gönderir.",
"LABEL_MEDIA_TITLE_PRIVACY": "Medya başlığı",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Medya başlıklarının odaya nasıl gönderileceğini seçin."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Medya başlıklarının odaya nasıl gönderileceğini seçin.",
"LABEL_SETTINGS_GROUP_PROFILE": "Profil ve Görünüm",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Kullanıcı adınızı, temanızı ve dil tercihlerinizi değiştirin.",
"LABEL_SETTINGS_GROUP_SYNC": "Oynatma ve Eşitleme",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Oynatma, bildirim ve ses tercihlerini özelleştirin."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "Пульт дистанційного керування",
"BTN_COPY_INVITE": "📋 Посилання на запрошення",
"BTN_COPY_INVITE_TOOLTIP": "Копіювати посилання для запрошення",
"BTN_PLAY": "Відтворити",
"BTN_PLAY": "Відтворити",
"BTN_PLAY_TOOLTIP": "Надішліть усім команду Play",
"BTN_PAUSE": "Пауза",
"BTN_PAUSE": "Пауза",
"BTN_PAUSE_TOOLTIP": "Надішліть команду паузи всім",
"BTN_SYNC": "⚡ СИНХР",
"BTN_SYNC": "Синхр",
"BTN_SYNC_TOOLTIP": "Змусити всіх користувачів синхронізуватися",
"OPTION_JUMP_TO_OTHERS": "Перейти до інших",
"OPTION_JUMP_TO_ME": "Перейти до мене",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "Застосуйте звукові ефекти, такі як стиснення, до відтворення відео",
"AUDIO_OPEN_SETTINGS": "Відкрити",
"NEW_FEATURE_AUDIO": "Новинка: обробка звуку — спробуйте компресор!",
"NEW_FEATURE_THEME": "Нове: Теми — перемкніться на класичний вигляд або мінімальний графіт.",
"AUDIO_BACK": "← Назад",
"AUDIO_PAGE_TITLE": "Параметри звуку",
"AUDIO_MASTER_TOGGLE": "Обробка аудіо",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "Надсилати назву вкладки",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "Надсилає до кімнати назву вибраної вкладки браузера.",
"LABEL_MEDIA_TITLE_PRIVACY": "Назва медіа",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Виберіть, як назви медіа надсилати до кімнати."
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "Виберіть, як назви медіа надсилати до кімнати.",
"LABEL_SETTINGS_GROUP_PROFILE": "Профіль та Вигляд",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "Змініть ім'я користувача, тему та мовні налаштування.",
"LABEL_SETTINGS_GROUP_SYNC": "Відтворення та Синхронізація",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "Налаштуйте відтворення, сповіщення та параметри звуку."
}
+9 -4
View File
@@ -70,11 +70,11 @@
"LABEL_REMOTE_CONTROL": "遥控",
"BTN_COPY_INVITE": "📋 邀请链接",
"BTN_COPY_INVITE_TOOLTIP": "复制邀请链接",
"BTN_PLAY": "播放",
"BTN_PLAY": "播放",
"BTN_PLAY_TOOLTIP": "向所有人发送播放命令",
"BTN_PAUSE": "暂停",
"BTN_PAUSE": "暂停",
"BTN_PAUSE_TOOLTIP": "向所有人发送暂停命令",
"BTN_SYNC": "同步",
"BTN_SYNC": "同步",
"BTN_SYNC_TOOLTIP": "强制所有用户同步",
"OPTION_JUMP_TO_OTHERS": "跳转到其他",
"OPTION_JUMP_TO_ME": "跳到我这里",
@@ -209,6 +209,7 @@
"LABEL_AUDIO_PROCESSING_TOOLTIP": "将压缩等音频效果应用于视频播放",
"AUDIO_OPEN_SETTINGS": "打开",
"NEW_FEATURE_AUDIO": "新功能:音频处理 - 尝试压缩器!",
"NEW_FEATURE_THEME": "新功能:主题 — 切换到经典外观或极简石墨风格。",
"AUDIO_BACK": "← 返回",
"AUDIO_PAGE_TITLE": "音频设置",
"AUDIO_MASTER_TOGGLE": "音频处理",
@@ -238,5 +239,9 @@
"LABEL_SEND_TAB_TITLE": "发送标签页标题",
"LABEL_SEND_TAB_TITLE_TOOLTIP": "将所选浏览器标签页的标题发送到房间。",
"LABEL_MEDIA_TITLE_PRIVACY": "媒体标题",
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "选择媒体标题发送到房间的方式。"
"LABEL_MEDIA_TITLE_PRIVACY_TOOLTIP": "选择媒体标题发送到房间的方式。",
"LABEL_SETTINGS_GROUP_PROFILE": "个人资料与外观",
"LABEL_SETTINGS_GROUP_PROFILE_TOOLTIP": "更改您的用户名、主题和语言首选项。",
"LABEL_SETTINGS_GROUP_SYNC": "播放与同步",
"LABEL_SETTINGS_GROUP_SYNC_TOOLTIP": "自定义播放、通知和音频首选项。"
}
+1 -1
View File
@@ -2,7 +2,7 @@
"manifest_version": 3,
"default_locale": "en",
"name": "KoalaSync",
"version": "2.5.3",
"version": "2.6.0",
"description": "Synchronize video playback on YouTube, Netflix, Emby, Jellyfin, and any HTML5 site in real-time with friends.",
"permissions": [
"storage",
+1189 -196
View File
File diff suppressed because it is too large Load Diff
+282 -68
View File
@@ -64,6 +64,8 @@ const elements = {
autoCopyInvite: document.getElementById('autoCopyInvite'),
cancelLobbyBtn: document.getElementById('cancelLobbyBtn'),
langSelector: document.getElementById('langSelector'),
themeSelector: document.getElementById('themeSelector'),
paletteSelector: document.getElementById('paletteSelector'),
audioSettingsLink: document.getElementById('audioSettingsLink'),
settingsSupportLink: document.getElementById('settingsSupportLink'),
@@ -114,6 +116,12 @@ const FEATURE_HINTS = [
selector: '#audioProcessingLabel',
position: 'beforebegin',
i18nTooltip: 'NEW_FEATURE_AUDIO'
},
{
key: 'theme_picker',
selector: '#paletteLabel',
position: 'afterend',
i18nTooltip: 'NEW_FEATURE_THEME'
}
];
@@ -132,6 +140,118 @@ function openAudioSettingsPage() {
chrome.tabs.create({ url: chrome.runtime.getURL('audio-options.html') });
}
function localizeThemeSelector(locale) {
const labels = {
de: ['Darstellung', 'System', 'Dunkel', 'Hell', 'Folge dem System-Design oder wähle ein festes Design'],
fr: ['Apparence', 'Système', 'Sombre', 'Clair', 'Suivre le thème du système ou choisir une apparence fixe'],
es: ['Apariencia', 'Sistema', 'Oscuro', 'Claro', 'Seguir el tema del sistema o elegir una apariencia fija'],
it: ['Aspetto', 'Sistema', 'Scuro', 'Chiaro', 'Segui il tema di sistema o scegli un aspetto fisso'],
nl: ['Weergave', 'Systeem', 'Donker', 'Licht', 'Volg het systeemthema of kies een vaste weergave'],
pl: ['Wygląd', 'System', 'Ciemny', 'Jasny', 'Dostosuj do motywu systemowego lub wybierz stały wygląd'],
pt: ['Aparência', 'Sistema', 'Escuro', 'Claro', 'Seguir o tema do sistema ou escolher uma aparência fixa'],
'pt-BR': ['Aparência', 'Sistema', 'Escuro', 'Claro', 'Seguir o tema do sistema ou escolher uma aparência fixa'],
tr: ['Görünüm', 'Sistem', 'Koyu', 'Açık', 'Sistem temasını takip et veya sabit bir görünüm seç'],
ru: ['Оформление', 'Системная', 'Тёмная', 'Светлая', 'Следовать системной теме или выбрать фиксированное оформление'],
ja: ['外観', 'システム', 'ダーク', 'ライト', 'システムテーマに従うか、固定の外観を選択します'],
ko: ['테마', '시스템', '다크', '라이트', '시스템 테마를 따르거나 고정된 테마를 선택하세요'],
zh: ['外观', '跟随系统', '深色', '浅色', '跟随系统主题或选择固定外观'],
uk: ['Вигляд', 'Системна', 'Темна', 'Світла', 'Дотримуватися системної теми або вибрати фіксоване оформлення'],
en: ['Appearance', 'System', 'Dark', 'Light', 'Follow the system theme or choose a fixed appearance']
};
const [label, system, dark, light, tooltip] = labels[locale] || labels.en;
const labelEl = document.getElementById('themeLabel');
const systemEl = document.getElementById('themeOptionSystem');
const darkEl = document.getElementById('themeOptionDark');
const lightEl = document.getElementById('themeOptionLight');
const systemButton = document.getElementById('themeChoiceSystem');
const darkButton = document.getElementById('themeChoiceDark');
const lightButton = document.getElementById('themeChoiceLight');
if (labelEl) {
labelEl.textContent = label;
if (tooltip) labelEl.setAttribute('title', tooltip);
}
if (systemEl) systemEl.textContent = system;
if (darkEl) darkEl.textContent = dark;
if (lightEl) lightEl.textContent = light;
if (systemButton) systemButton.textContent = system;
if (darkButton) darkButton.textContent = dark;
if (lightButton) lightButton.textContent = light;
if (elements.themeSelector) elements.themeSelector.setAttribute('aria-label', label);
// The palette scheme names (Eucalyptus / Cyber / Graphite) are brand
// words kept verbatim; only the row label is localized.
const paletteLabels = {
de: ['Farbschema', 'Wähle ein kuratiertes Farbschema für die Erweiterung'],
fr: ['Thème', 'Choisissez une palette de couleurs personnalisée pour l\'extension'],
es: ['Tema', 'Elige una paleta de colores seleccionada para la extensión'],
it: ['Tema', 'Scegli una combinazione di colori curata per l\'estensione'],
nl: ['Thema', 'Kies een samengesteld kleurenschema voor de extensie'],
pl: ['Motyw', 'Wybierz dopasowany schemat kolorów dla rozszerzenia'],
pt: ['Tema', 'Escolha um esquema de cores personalizado para a extensão'],
'pt-BR': ['Tema', 'Escolha um esquema de cores personalizado para a extensão'],
tr: ['Tema', 'Uzantı için özel olarak seçilmiş bir renk şeması seçin'],
ru: ['Тема', 'Выберите цветовую схему для расширения'],
ja: ['テーマ', '拡張機能の厳選された配色を選択します'],
ko: ['테마', '확장 프로그램에 맞는 특별한 색상 테마를 선택하세요'],
zh: ['主题', '为扩展程序选择精心设计的配色方案'],
uk: ['Тема', 'Виберіть колірну схему для розширення'],
en: ['Theme', 'Pick a curated colour scheme for the extension']
};
const [paletteLabel, paletteTooltip] = paletteLabels[locale] || paletteLabels.en;
const paletteLabelEl = document.getElementById('paletteLabel');
if (paletteLabelEl) {
paletteLabelEl.textContent = paletteLabel;
if (paletteTooltip) paletteLabelEl.setAttribute('title', paletteTooltip);
}
if (elements.paletteSelector) elements.paletteSelector.setAttribute('aria-label', paletteLabel);
// Micro-descriptors under each swatch card: [nature, classic, minimal].
const paletteDescs = {
de: ['Natur', 'Klassik', 'Minimal'], fr: ['Nature', 'Classique', 'Minimal'],
es: ['Naturaleza', 'Clásico', 'Minimal'], it: ['Natura', 'Classico', 'Minimal'],
nl: ['Natuur', 'Klassiek', 'Minimaal'], pl: ['Natura', 'Klasyczny', 'Minimal'],
pt: ['Natureza', 'Clássico', 'Minimal'], 'pt-BR': ['Natureza', 'Clássico', 'Minimal'],
tr: ['Doğa', 'Klasik', 'Minimal'], ru: ['Природа', 'Классика', 'Минимал'],
ja: ['ネイチャー', 'クラシック', 'ミニマル'], ko: ['자연', '클래식', '미니멀'],
zh: ['自然', '经典', '极简'], uk: ['Природа', 'Класика', 'Мінімал'],
en: ['Nature', 'Classic', 'Minimal']
};
const [natureDesc, classicDesc, minimalDesc] = paletteDescs[locale] || paletteDescs.en;
const descMap = { eucalyptus: natureDesc, cyber: classicDesc, graphite: minimalDesc };
document.querySelectorAll('.palette-choice').forEach(btn => {
const desc = btn.querySelector('.palette-desc');
if (desc) desc.textContent = descMap[btn.dataset.paletteValue] || desc.textContent;
});
}
function syncThemePicker() {
const activeMode = elements.themeSelector?.value || 'system';
document.querySelectorAll('.theme-choice').forEach(button => {
const active = button.dataset.themeValue === activeMode;
button.classList.toggle('active', active);
button.setAttribute('aria-pressed', String(active));
});
}
function syncPalettePicker() {
const activePalette = elements.paletteSelector?.value || 'eucalyptus';
document.querySelectorAll('.palette-choice').forEach(button => {
const active = button.dataset.paletteValue === activePalette;
button.classList.toggle('active', active);
button.setAttribute('aria-pressed', String(active));
});
}
// Briefly enable global colour transitions so a theme/appearance switch
// cross-fades instead of snapping. Self-clearing; a no-op under reduced motion.
let themeAnimTimer = null;
function flashThemeTransition() {
const root = document.documentElement;
root.classList.add('theme-anim');
if (themeAnimTimer) clearTimeout(themeAnimTimer);
themeAnimTimer = setTimeout(() => root.classList.remove('theme-anim'), 300);
}
async function updateFeatureHints() {
const data = await chrome.storage.sync.get(['dismissedHints']);
const dismissed = Array.isArray(data.dismissedHints) ? data.dismissedHints : [];
@@ -204,7 +324,7 @@ function setRoomRefreshCooldown() {
async function init() {
// Local-only by design — settings and room credentials never come from
// storage.sync (only onboardingComplete + dismissedHints live there).
const localData = await chrome.storage.local.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username', 'filterNoise', 'autoSyncNextEpisode', 'sendTabTitle', 'mediaTitlePrivacyMode', 'titlePrivacyMode', 'forceSyncMode', 'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings', 'activeTab']);
const localData = await chrome.storage.local.get(['serverUrl', 'useCustomServer', 'roomId', 'password', 'username', 'filterNoise', 'autoSyncNextEpisode', 'sendTabTitle', 'mediaTitlePrivacyMode', 'titlePrivacyMode', 'forceSyncMode', 'browserNotifications', 'autoCopyInvite', 'locale', 'audioSettings', 'activeTab', 'themeMode', 'themePalette']);
let activeLang = localData.locale;
if (!activeLang) {
@@ -214,8 +334,13 @@ async function init() {
await loadLocale(activeLang);
translateDOM();
localizeThemeSelector(activeLang);
if (elements.langSelector) elements.langSelector.value = activeLang;
if (elements.themeSelector) elements.themeSelector.value = ['dark', 'light'].includes(localData.themeMode) ? localData.themeMode : 'system';
if (elements.paletteSelector) elements.paletteSelector.value = ['cyber', 'graphite'].includes(localData.themePalette) ? localData.themePalette : 'eucalyptus';
syncThemePicker();
syncPalettePicker();
let username = localData.username;
if (!username) {
@@ -476,8 +601,8 @@ function updateLastActionUI(state, peers) {
const safeAcks = state.acks || [];
const actionNames = {
'play': getMessage('BTN_PLAY').replace('▶ ', '').toUpperCase(),
'pause': getMessage('BTN_PAUSE').replace('⏸ ', '').toUpperCase(),
'play': getMessage('BTN_PLAY'),
'pause': getMessage('BTN_PAUSE'),
'seek': getMessage('NOTIF_SEEK').toUpperCase(),
'force_sync_prepare': getMessage('BTN_STATE_SYNCING').toUpperCase(),
'force_sync_execute': getMessage('BTN_STATE_SYNCED').toUpperCase()
@@ -500,7 +625,7 @@ function updateLastActionUI(state, peers) {
actionSpan.textContent = actionNames[state.action] || state.action.toUpperCase();
const infoSpan = document.createElement('span');
infoSpan.style.cssText = 'font-size:9px; color:var(--text-muted);';
infoSpan.style.cssText = 'font-size:10px; color:var(--text-muted);';
infoSpan.textContent = `${senderName} @ ${timeStr}`;
header.appendChild(actionSpan);
@@ -509,14 +634,14 @@ function updateLastActionUI(state, peers) {
if (state.targetTime !== undefined && state.action === 'seek') {
const timeInfo = document.createElement('div');
timeInfo.style.cssText = 'font-size:9px; color:var(--text-muted); margin-top:4px;';
timeInfo.style.cssText = 'font-size:10px; color:var(--text-muted); margin-top:4px;';
timeInfo.textContent = `Target: ${formatTime(state.targetTime)}`;
elements.lastActionCard.appendChild(timeInfo);
}
if (state.targetTime !== undefined && state.action.includes('force_sync')) {
const timeInfo = document.createElement('div');
timeInfo.style.cssText = 'font-size:9px; color:var(--text-muted); margin-top:4px;';
timeInfo.style.cssText = 'font-size:10px; color:var(--text-muted); margin-top:4px;';
timeInfo.textContent = `Sync to: ${formatTime(state.targetTime)}`;
elements.lastActionCard.appendChild(timeInfo);
}
@@ -529,7 +654,7 @@ function updateLastActionUI(state, peers) {
if (pId === localPeerId) return;
const pName = (typeof peer === 'object' && peer.username) ? peer.username : pId.substring(0, 4);
const isAcked = safeAcks.includes(pId) || pId === state.senderId;
const color = isAcked ? 'var(--success)' : '#475569';
const color = isAcked ? 'var(--success)' : 'var(--border-strong)';
const icon = isAcked ? '✓' : '...';
const avatar = getAvatarForName(pName);
@@ -538,11 +663,11 @@ function updateLastActionUI(state, peers) {
peerItem.style.cssText = `display:flex; flex-direction:column; align-items:center; opacity: ${isAcked ? 1 : 0.6};`;
const dot = document.createElement('div');
dot.style.cssText = `width:18px; height:18px; border-radius:50%; background:${color}; color:white; display:flex; align-items:center; justify-content:center; font-size:9px; font-weight:bold; margin-bottom:1px;`;
dot.style.cssText = `width:18px; height:18px; border-radius:50%; background:${color}; color:${isAcked ? 'var(--text-on-green)' : 'var(--text-primary)'}; display:flex; align-items:center; justify-content:center; font-size:9px; font-weight:bold; margin-bottom:1px;`;
dot.textContent = icon;
const nameSpan = document.createElement('span');
nameSpan.style.cssText = 'font-size:7px; color:var(--text-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:36px;';
nameSpan.style.cssText = 'font-size:9px; color:var(--text-muted); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:42px;';
nameSpan.textContent = `${avatar} ${pName}`;
peerItem.appendChild(dot);
@@ -630,7 +755,10 @@ function renderEmpty(container, type) {
copyBtn.title = getMessage('BTN_COPY_INVITE_TOOLTIP');
copyBtn.addEventListener('click', () => {
navigator.clipboard.writeText(elements.inviteLink.value)
.then(() => showToast(getMessage('TOAST_INVITE_COPIED'), 'success', 2000))
.then(() => {
showToast(getMessage('TOAST_INVITE_COPIED'), 'success', 2000);
spawnLeafBurst(copyBtn);
})
.catch(() => showToast(getMessage('TOAST_COPY_FAILED'), 'error'));
});
wrapper.appendChild(copyBtn);
@@ -676,7 +804,7 @@ function updatePeerList(peers) {
const peerItem = document.createElement('div');
peerItem.className = 'peer-item';
peerItem.style.cssText = 'position:relative; display:block; padding: 8px 0; border-bottom: 1px solid rgba(255,255,255,0.05);';
peerItem.style.cssText = 'position:relative; display:block; padding: 8px 0; border-bottom: 1px solid var(--border-soft);';
const header = document.createElement('div');
header.style.cssText = 'display:flex; justify-content:space-between; align-items:center; padding-right: 24px;';
@@ -686,7 +814,7 @@ function updatePeerList(peers) {
const avatar = getAvatarForName(pUsername || pId);
if (pUsername) {
const u = document.createElement('span');
u.style.cssText = 'font-weight:600; color:white; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; display: inline-block;';
u.style.cssText = 'font-weight:600; color:var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 120px; display: inline-block;';
u.textContent = `${avatar} ${pUsername}`;
const i = document.createElement('span');
i.style.cssText = 'font-size:10px; opacity:0.6; font-style:italic; white-space: nowrap; flex-shrink: 0;';
@@ -725,7 +853,7 @@ function updatePeerList(peers) {
// Host Control Mode: show "Solo" badge for peers watching on their own.
if (typeof p === 'object' && p.desynced) {
const solo = document.createElement('span');
solo.style.cssText = 'font-size:10px; color:#fff; background:#b45309; padding:2px 6px; border-radius:6px; font-weight:600;';
solo.style.cssText = 'font-size:10px; color:var(--text-on-warm); background:var(--accent-terracotta); padding:2px 6px; border-radius:6px; font-weight:700;';
const soloText = getMessage('BADGE_DESYNCED') || 'Solo';
solo.textContent = soloText;
solo.title = getMessage('TOOLTIP_PEER_DESYNCED') || soloText;
@@ -742,7 +870,7 @@ function updatePeerList(peers) {
const isController = !isOwner && hcmControllers.includes(pId);
if (isOwner || isController) {
const roleBadge = document.createElement('span');
roleBadge.style.cssText = 'font-size:10px; color:#fff; background:var(--accent); padding:2px 6px; border-radius:6px; font-weight:600;';
roleBadge.style.cssText = 'font-size:10px; color:var(--text-on-green); background:var(--accent); padding:2px 6px; border-radius:6px; font-weight:700;';
roleBadge.textContent = isOwner ? (getMessage('BADGE_HOST') || 'Host') : (getMessage('BADGE_CONTROLLER') || 'Controller');
rightGroup.appendChild(roleBadge);
}
@@ -755,7 +883,7 @@ function updatePeerList(peers) {
btn.title = revoke ? (getMessage('BTN_REVOKE_CONTROL') || 'Revoke') : (getMessage('BTN_GIVE_CONTROL') || 'Give control');
btn.addEventListener('mouseenter', () => {
btn.style.background = revoke ? 'var(--text-muted)' : 'var(--accent)';
btn.style.color = '#fff';
btn.style.color = 'var(--text-on-green)';
});
btn.addEventListener('mouseleave', () => {
btn.style.background = 'transparent';
@@ -1011,25 +1139,8 @@ function applyConnectionStatus(status) {
const idle = status === 'idle';
if (elements.connDot) {
elements.connDot.className = 'status-dot ' + (connected ? 'status-online' : ((connecting || reconnecting) ? 'status-online' : 'status-offline'));
if (reconnecting) {
elements.connDot.style.background = '#f59e0b';
elements.connDot.style.boxShadow = '0 0 8px #f59e0b';
} else if (connecting) {
elements.connDot.style.background = '#fbbf24';
elements.connDot.style.boxShadow = '0 0 8px #fbbf24';
} else if (idle) {
// Neutral grey — ready, not failed.
elements.connDot.style.background = '#9ca3af';
elements.connDot.style.boxShadow = 'none';
} else if (!connected) {
elements.connDot.style.background = '#ef4444';
elements.connDot.style.boxShadow = 'none';
} else {
elements.connDot.style.background = '';
elements.connDot.style.boxShadow = '';
}
const dotStatus = connected ? 'status-online' : ((connecting || reconnecting) ? 'status-connecting' : (idle ? 'status-idle' : 'status-offline'));
elements.connDot.className = `status-dot ${dotStatus}`;
}
if (elements.connText) {
@@ -1066,16 +1177,16 @@ function updatePingDisplay(pingMs) {
if (!elements.connPing) return;
if (pingMs === null || pingMs === undefined || typeof pingMs !== 'number' || !Number.isFinite(pingMs)) {
elements.connPing.textContent = '';
elements.connPing.style.color = '';
elements.connPing.className = 'conn-ping';
return;
}
elements.connPing.textContent = `${Math.round(pingMs)}ms`;
if (pingMs < 50) {
elements.connPing.style.color = '#22c55e';
if (pingMs < 75) {
elements.connPing.className = 'conn-ping conn-ping-good';
} else if (pingMs < 150) {
elements.connPing.style.color = '#f59e0b';
elements.connPing.className = 'conn-ping conn-ping-warning';
} else {
elements.connPing.style.color = '#ef4444';
elements.connPing.className = 'conn-ping conn-ping-bad';
}
}
@@ -1093,10 +1204,10 @@ function updateHistory(history) {
const actionLabel = item.action.toUpperCase().replace('FORCE_SYNC_', '');
const entry = document.createElement('div');
entry.style.cssText = 'margin-bottom: 4px; border-bottom: 1px solid rgba(255,255,255,0.05); padding-bottom: 2px;';
entry.style.cssText = 'margin-bottom: 4px; border-bottom: 1px solid var(--border-soft); padding-bottom: 2px;';
const timeSpan = document.createElement('span');
timeSpan.style.color = '#64748b';
timeSpan.style.color = 'var(--text-muted)';
timeSpan.textContent = `[${time}] `;
const actionBold = document.createElement('b');
@@ -1139,7 +1250,7 @@ function updateRoomList(rooms) {
rooms.forEach(r => {
const item = document.createElement('div');
item.className = 'room-item';
item.style.cssText = 'display:flex; justify-content:space-between; align-items:center; padding: 8px; border-bottom: 1px solid rgba(255,255,255,0.05); cursor:pointer;';
item.style.cssText = 'display:flex; justify-content:space-between; align-items:center; padding: 8px; border-bottom: 1px solid var(--border-soft); cursor:pointer;';
item.dataset.id = r.id;
const leftSide = document.createElement('div');
@@ -1273,6 +1384,43 @@ if (elements.autoCopyInvite) {
});
}
if (elements.themeSelector) {
elements.themeSelector.addEventListener('change', () => {
const themeMode = elements.themeSelector.value;
flashThemeTransition();
window.koalaTheme?.setMode(themeMode);
chrome.storage.local.set({ themeMode });
syncThemePicker();
});
}
document.querySelectorAll('.theme-choice').forEach(button => {
button.addEventListener('click', () => {
if (!elements.themeSelector) return;
elements.themeSelector.value = button.dataset.themeValue;
elements.themeSelector.dispatchEvent(new window.Event('change'));
});
});
if (elements.paletteSelector) {
elements.paletteSelector.addEventListener('change', () => {
const themePalette = elements.paletteSelector.value;
flashThemeTransition();
window.koalaTheme?.setPalette(themePalette);
chrome.storage.local.set({ themePalette });
syncPalettePicker();
dismissFeatureHint('theme_picker');
});
}
document.querySelectorAll('.palette-choice').forEach(button => {
button.addEventListener('click', () => {
if (!elements.paletteSelector) return;
elements.paletteSelector.value = button.dataset.paletteValue;
elements.paletteSelector.dispatchEvent(new window.Event('change'));
});
});
if (elements.audioSettingsLink) {
elements.audioSettingsLink.addEventListener('click', async (event) => {
event.preventDefault();
@@ -1305,6 +1453,7 @@ if (elements.langSelector) {
await chrome.storage.local.set({ locale: selectedLang });
await loadLocale(selectedLang);
translateDOM();
localizeThemeSelector(selectedLang);
configureFooterLinks();
await updateFeatureHints();
@@ -1337,6 +1486,19 @@ if (elements.langSelector) {
});
}
// Accordion behavior for settings details categories (collapses others when one opens)
document.querySelectorAll('#tab-settings details.form-group').forEach(det => {
det.addEventListener('toggle', () => {
if (det.open) {
document.querySelectorAll('#tab-settings details.form-group').forEach(other => {
if (other !== det && other.open) {
other.removeAttribute('open');
}
});
}
});
});
elements.serverUrl.addEventListener('change', () => {
let url = elements.serverUrl.value.trim();
if (url && !url.includes('://')) {
@@ -1389,6 +1551,39 @@ function showToast(message, type = 'info', duration = 3000) {
setTimeout(() => toast.remove(), duration);
}
// Eucalyptus confetti: a few tiny leaves burst from the given element
// (matches the website's copy-invite moment). Subtle by design — few,
// tiny, short-lived — and skipped entirely under reduced motion.
function spawnLeafBurst(sourceEl) {
if (!sourceEl || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const rect = sourceEl.getBoundingClientRect();
if (!rect.width) return;
const originY = rect.top + rect.height / 2;
const count = 4 + Math.floor(Math.random() * 3);
for (let i = 0; i < count; i++) {
const leaf = document.createElement('span');
// Three tones of the palette: deep green, sage, a dash of amber
const tone = Math.random();
leaf.className = 'click-leaf' + (tone < 0.25 ? ' click-leaf-amber' : tone < 0.55 ? ' click-leaf-sage' : '');
// Fan out upward to a burst peak spread across the button's width;
// the keyframes brake there and let each leaf sink while it rocks.
const angle = (-90 + (Math.random() - 0.5) * 150) * Math.PI / 180;
const dist = 18 + Math.random() * 24;
const dur = 0.85 + Math.random() * 0.4;
leaf.style.left = (rect.left + 4 + Math.random() * Math.max(1, rect.width - 8)) + 'px';
leaf.style.top = (originY - rect.height * 0.2) + 'px';
leaf.style.setProperty('--leaf-x', (Math.cos(angle) * dist).toFixed(1) + 'px');
leaf.style.setProperty('--leaf-y', (Math.sin(angle) * dist).toFixed(1) + 'px');
leaf.style.setProperty('--leaf-rot', ((Math.random() - 0.5) * 160).toFixed(0) + 'deg');
leaf.style.setProperty('--leaf-scale', (0.55 + Math.random() * 0.55).toFixed(2));
leaf.style.setProperty('--leaf-dur', dur.toFixed(2) + 's');
leaf.style.setProperty('--flutter-dur', (0.35 + Math.random() * 0.3).toFixed(2) + 's');
leaf.appendChild(document.createElement('i'));
document.body.appendChild(leaf);
setTimeout(() => leaf.remove(), dur * 1000 + 150);
}
}
function showError(msg) {
if (!elements.roomError) return;
const currentToken = ++errorToken;
@@ -1775,14 +1970,13 @@ elements.copyInvite.addEventListener('click', () => {
navigator.clipboard.writeText(elements.inviteLink.value).then(() => {
const original = elements.copyInvite.textContent;
elements.copyInvite.textContent = '✓';
elements.copyInvite.style.background = 'var(--success)';
elements.copyInvite.style.color = 'white';
elements.copyInvite.classList.add('copy-success');
showToast(getMessage('TOAST_INVITE_COPIED'), 'success', 2000);
spawnLeafBurst(elements.copyInvite);
setTimeout(() => {
elements.copyInvite.textContent = original;
elements.copyInvite.style.background = '';
elements.copyInvite.style.color = '';
}, 2000);
elements.copyInvite.classList.remove('copy-success');
}, 1500);
}).catch(() => {
showToast(getMessage('TOAST_COPY_FAILED'), 'error');
});
@@ -1792,13 +1986,14 @@ if (elements.syncTabCopyInvite) {
elements.syncTabCopyInvite.addEventListener('click', () => {
navigator.clipboard.writeText(elements.inviteLink.value).then(() => {
const original = elements.syncTabCopyInvite.textContent;
elements.syncTabCopyInvite.textContent = '✓';
elements.syncTabCopyInvite.style.color = 'var(--success)';
elements.syncTabCopyInvite.textContent = '✓ Copied';
elements.syncTabCopyInvite.classList.add('copy-success');
showToast(getMessage('TOAST_INVITE_COPIED'), 'success', 2000);
spawnLeafBurst(elements.syncTabCopyInvite);
setTimeout(() => {
elements.syncTabCopyInvite.textContent = original;
elements.syncTabCopyInvite.style.color = '';
}, 2000);
elements.syncTabCopyInvite.classList.remove('copy-success');
}, 1500);
});
});
}
@@ -2259,7 +2454,7 @@ function refreshDebugInfo() {
const addSection = (title) => {
const div = document.createElement('div');
div.style.cssText = 'margin: 8px 0 4px 0; border-bottom: 1px solid #334155; padding-bottom: 2px; color: var(--accent); font-weight: bold; font-size: 10px; text-transform: uppercase;';
div.style.cssText = 'margin: 8px 0 4px 0; border-bottom: 1px solid var(--border-soft); padding-bottom: 2px; color: var(--accent); font-weight: bold; font-size: 10px; text-transform: uppercase;';
div.textContent = title;
elements.videoDebug.appendChild(div);
};
@@ -2268,7 +2463,7 @@ function refreshDebugInfo() {
// No video found — show diagnostic info
addSection('Video Detection');
const notFound = document.createElement('div');
notFound.style.cssText = 'color: #ef4444; font-weight: 700; margin-bottom: 8px;';
notFound.style.cssText = 'color: var(--status-error-text); font-weight: 700; margin-bottom: 8px;';
notFound.textContent = 'NO VIDEO ELEMENT FOUND';
elements.videoDebug.appendChild(notFound);
@@ -2286,7 +2481,7 @@ function refreshDebugInfo() {
}
const hint = document.createElement('div');
hint.style.cssText = 'margin-top: 12px; padding: 8px; background: rgba(251,191,36,0.1); border-left: 3px solid #fbbf24; border-radius: 4px; font-size: 10px; color: var(--text-muted);';
hint.style.cssText = 'margin-top: 12px; padding: 8px; background: color-mix(in oklch, var(--warning), transparent 88%); border-left: 3px solid var(--warning); border-radius: 4px; font-size: 10px; color: var(--text);';
hint.textContent = 'Is a video currently playing? The extension only detects <video> elements. Ensure media is actively loaded on the page.';
elements.videoDebug.appendChild(hint);
return;
@@ -2294,12 +2489,12 @@ function refreshDebugInfo() {
// Video found — full debug
addSection('Playback');
addField('State', state.paused ? 'PAUSED' : 'PLAYING', state.paused ? 'var(--text-muted)' : '#22c55e');
addField('State', state.paused ? 'PAUSED' : 'PLAYING', state.paused ? 'var(--text-muted)' : 'var(--status-success-text)');
addField('Time', `${state.currentTime.toFixed(2)}s / ${(state.duration || 0).toFixed(2)}s`);
addField('ReadyState', `${state.readyState} (${state.readyStateLabel || '?'})`,
state.readyState >= 3 ? '#22c55e' : '#fbbf24');
state.readyState >= 3 ? 'var(--status-success-text)' : 'var(--status-warning-text)');
addField('Network', `${state.networkState} (${state.networkStateLabel || '?'})`,
state.networkState === 1 ? '#22c55e' : state.networkState === 3 ? '#ef4444' : 'var(--text-muted)');
state.networkState === 1 ? 'var(--status-success-text)' : state.networkState === 3 ? 'var(--status-error-text)' : 'var(--text-muted)');
addField('Buffered', state.buffered || '?');
if (state.nativeCurrentTime != null || state.nativeDuration != null) {
addField('Native Time', `${state.nativeCurrentTime ?? '?'}s / ${state.nativeDuration ?? '?'}s`);
@@ -2323,18 +2518,18 @@ function refreshDebugInfo() {
addSection('Dimensions');
const dimsOk = state.videoWidth > 0 && state.videoHeight > 0;
addField('Resolution', `${state.videoWidth}x${state.videoHeight}`, dimsOk ? '#22c55e' : '#ef4444');
addField('Resolution', `${state.videoWidth}x${state.videoHeight}`, dimsOk ? 'var(--status-success-text)' : 'var(--status-error-text)');
if (!dimsOk) {
const dimHint = document.createElement('div');
dimHint.style.cssText = 'color: #fbbf24; font-size: 9px; margin: 2px 0 6px 12px;';
dimHint.style.cssText = 'color: var(--status-warning-text); font-size: 10px; margin: 2px 0 6px 12px;';
dimHint.textContent = '0x0 = video element hidden or not yet loaded';
elements.videoDebug.appendChild(dimHint);
}
if (state.error) {
addSection('Media Error');
addField('Code', String(state.error.code), '#ef4444');
addField('Message', state.error.message || '?', '#ef4444');
addField('Code', String(state.error.code), 'var(--status-error-text)');
addField('Message', state.error.message || '?', 'var(--status-error-text)');
}
addSection('Detection');
@@ -2408,9 +2603,10 @@ function updateLobbyUI(lobby, peers) {
elements.episodeLobbyCard.style.display = 'block';
elements.lobbyTitle.textContent = getMessage('LOBBY_WAITING_FOR', { title: lobby.expectedTitle });
// Build peer readiness list
// Build peer readiness list. Peer usernames are remote-controlled input, so
// every node is built with the DOM API and filled via textContent.
const readySet = new Set(lobby.readyPeers || []);
const peerLines = [];
const peerItems = [];
if (peers && peers.length > 0) {
peers.forEach(p => {
@@ -2418,14 +2614,29 @@ function updateLobbyUI(lobby, peers) {
const pName = (typeof p === 'object' && p.username) ? p.username : pId;
const avatar = getAvatarForName(pName);
const isReady = readySet.has(pId);
const icon = isReady ? '\u2705' : '\u23f3';
const icon = isReady ? '' : '';
const label = isReady ? getMessage('LABEL_LOBBY_PEER_READY') : getMessage('LABEL_LOBBY_PEER_LOADING');
peerLines.push(`${icon} ${avatar} ${pName} \u2014 ${label}`);
const badgeClass = isReady ? 'badge-ready' : 'badge-loading';
const item = document.createElement('span');
item.className = 'lobby-peer-item';
item.appendChild(document.createTextNode(`${icon} ${avatar} ${pName} `));
const badge = document.createElement('span');
badge.className = `badge ${badgeClass}`;
badge.textContent = label;
item.appendChild(badge);
peerItems.push(item);
});
}
if (peerLines.length > 0 && elements.lobbyPeerStatus) {
elements.lobbyPeerStatus.textContent = peerLines.join(' | ');
if (peerItems.length > 0 && elements.lobbyPeerStatus) {
elements.lobbyPeerStatus.textContent = '';
peerItems.forEach((item, index) => {
if (index > 0) elements.lobbyPeerStatus.appendChild(document.createTextNode(' '));
elements.lobbyPeerStatus.appendChild(item);
});
} else if (elements.lobbyPeerStatus) {
elements.lobbyPeerStatus.textContent = getMessage('LOBBY_WAITING_PEERS');
}
@@ -2433,7 +2644,10 @@ function updateLobbyUI(lobby, peers) {
// Show elapsed time
if (lobby.createdAt && elements.lobbyPeerStatus) {
const elapsed = Math.floor((Date.now() - lobby.createdAt) / 1000);
elements.lobbyPeerStatus.textContent += ` (${elapsed}s)`;
const timerSpan = document.createElement('span');
timerSpan.style.cssText = 'font-size: 10px; color: var(--text-muted); margin-left: 6px; display: inline-block; vertical-align: middle;';
timerSpan.textContent = `(${elapsed}s)`;
elements.lobbyPeerStatus.appendChild(timerSpan);
}
}
+45
View File
@@ -0,0 +1,45 @@
(() => {
const systemTheme = window.matchMedia('(prefers-color-scheme: light)');
let mode = 'system';
let palette = 'eucalyptus';
const normalize = value => ['system', 'dark', 'light'].includes(value) ? value : 'system';
const normalizePalette = value => ['eucalyptus', 'cyber', 'graphite'].includes(value) ? value : 'eucalyptus';
const apply = value => {
mode = normalize(value);
const light = mode === 'light' || (mode === 'system' && systemTheme.matches);
document.documentElement.classList.toggle('theme-light', light);
document.documentElement.dataset.theme = light ? 'light' : 'dark';
document.documentElement.style.colorScheme = light ? 'light' : 'dark';
};
const applyPalette = value => {
palette = normalizePalette(value);
document.documentElement.dataset.palette = palette;
};
apply('system');
applyPalette('eucalyptus');
window.koalaTheme = {
getMode: () => mode,
setMode: apply,
getPalette: () => palette,
setPalette: applyPalette
};
systemTheme.addEventListener('change', () => {
if (mode === 'system') apply('system');
});
if (!globalThis.chrome?.storage?.local) return;
chrome.storage.local.get(['themeMode', 'themePalette'], data => {
apply(data.themeMode);
applyPalette(data.themePalette);
});
chrome.storage.onChanged.addListener((changes, area) => {
if (area !== 'local') return;
if (changes.themeMode) apply(changes.themeMode.newValue);
if (changes.themePalette) applyPalette(changes.themePalette.newValue);
});
})();
+1 -1
View File
@@ -19,7 +19,7 @@ export function normalizeSendTabTitle(sendTabTitle, legacyMode = TITLE_PRIVACY_M
export function normalizeTabTitle(title) {
if (typeof title !== 'string') return null;
const normalized = title.replace(/^\s*(?:\(\d{1,2}\)|\[\d{1,2}\])\s+/, '').trim();
const normalized = title.replace(/^\s*(?:\(\d+\+?\)|\[\d+\+?\])\s+/, '').trim();
return normalized.length > 0 ? normalized : null;
}
+1925 -11
View File
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -1,6 +1,6 @@
{
"name": "koalasync",
"version": "2.5.3",
"version": "2.6.0",
"description": "KoalaSync Build Scripts",
"private": true,
"type": "module",
@@ -9,6 +9,7 @@
"indexnow": "node website/submit-indexnow.cjs",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"subset-flags": "node website/tools/subset-flag-font.mjs",
"test": "npm run verify",
"test:unit": "vitest run",
"verify": "node scripts/verify-release.mjs"
@@ -16,10 +17,13 @@
"devDependencies": {
"@playwright/test": "^1.61.1",
"@vitest/coverage-v8": "^4.1.9",
"addons-linter": "^10.9.0",
"archiver": "^7.0.1",
"esbuild": "^0.28.1",
"eslint": "^10.4.0",
"eslint-plugin-no-unsanitized": "^4.1.5",
"fs-extra": "^11.2.0",
"htmlnano": "^3.4.0",
"sharp": "^0.34.5",
"svgo": "^4.0.1",
"vitest": "^4.1.9"
+6 -1
View File
@@ -18,7 +18,12 @@ assert.equal(normalizeSendTabTitle(true, TITLE_PRIVACY_MODES.HIDDEN), true);
assert.equal(normalizeSendTabTitle(false, TITLE_PRIVACY_MODES.FULL), false);
assert.equal(normalizeTabTitle('(12) Testvideo - YouTube'), 'Testvideo - YouTube');
assert.equal(normalizeTabTitle('[7] Testvideo - YouTube'), 'Testvideo - YouTube');
assert.equal(normalizeTabTitle('(500) Days of Summer'), '(500) Days of Summer');
assert.equal(normalizeTabTitle('(99+) Testvideo - YouTube'), 'Testvideo - YouTube');
assert.equal(normalizeTabTitle('(999+) Testvideo - YouTube'), 'Testvideo - YouTube');
assert.equal(normalizeTabTitle('[999+] Testvideo - YouTube'), 'Testvideo - YouTube');
assert.equal(normalizeTabTitle('(500) Days of Summer'), 'Days of Summer');
assert.equal(normalizeTabTitle('(101) Days of Summer'), 'Days of Summer');
assert.equal(normalizeTabTitle('[101] Days of Summer'), 'Days of Summer');
assert.equal(normalizeTabTitle(' '), null);
assert.equal(sanitizeTabTitle('Private Tab', true), 'Private Tab');
+183
View File
@@ -0,0 +1,183 @@
#!/usr/bin/env node
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const template = fs.readFileSync(path.join(repoRoot, 'website', 'template.html'), 'utf8');
const app = fs.readFileSync(path.join(repoRoot, 'website', 'app.js'), 'utf8');
const langInit = fs.readFileSync(path.join(repoRoot, 'website', 'lang-init.js'), 'utf8');
const demoCss = fs.readFileSync(path.join(repoRoot, 'website', 'styles', 'demo.css'), 'utf8');
const landingPrimaryCss = fs.readFileSync(path.join(repoRoot, 'website', 'styles', 'landing-primary.css'), 'utf8');
const legalCss = fs.readFileSync(path.join(repoRoot, 'website', 'styles', 'legal.css'), 'utf8');
const joinPage = fs.readFileSync(path.join(repoRoot, 'website', 'join.html'), 'utf8');
const imprintPage = fs.readFileSync(path.join(repoRoot, 'website', 'imprint.html'), 'utf8');
const germanImprintPage = fs.readFileSync(path.join(repoRoot, 'website', 'impressum-de.html'), 'utf8');
const alternativesIndex = fs.readFileSync(path.join(repoRoot, 'website', 'alternatives', 'index.html'), 'utf8');
const alternativesCss = fs.readFileSync(path.join(repoRoot, 'website', 'styles', 'alternatives.css'), 'utf8');
const llmsText = fs.readFileSync(path.join(repoRoot, 'website', 'llms.txt'), 'utf8');
const mockupStart = template.indexOf('<div class="extension-mockup">');
const mockupEnd = template.indexOf('<div class="demo-invite-fly"', mockupStart);
if (mockupStart === -1 || mockupEnd === -1) {
throw new Error('Could not locate the extension mockup in website/template.html');
}
const mockup = template.slice(mockupStart, mockupEnd);
const themeSensitiveControls = [
['video selector', /<select[^>]+id="demo-video-select"[^>]+>/],
['sync target', /<div[^>]+class="mock-input"[^>]+title="Choose sync target"[^>]*>/],
['WebSocket status', /<span style="[^"]*flex:1;[^"]*">\s*\{\{MOCK_27\}\}/]
];
for (const [label, pattern] of themeSensitiveControls) {
const match = mockup.match(pattern);
if (!match) throw new Error(`Could not locate ${label} in the extension mockup`);
if (!/color:\s*var\(--text\)/.test(match[0])) {
throw new Error(`${label} must use var(--text) so it remains readable in both themes`);
}
}
const landingStylesheets = [...template.matchAll(/<link\b[^>]*\brel="stylesheet"[^>]*\bhref="\{\{ASSET_PATH\}\}landing[^">]*"[^>]*>/g)];
if (landingStylesheets.length !== 1) {
throw new Error(`Landing must load exactly one render-blocking stylesheet; found ${landingStylesheets.length}`);
}
const llmsLinks = [...template.matchAll(/<link\b[^>]*\brel="alternate"[^>]*\btype="text\/markdown"[^>]*\bhref="https:\/\/sync\.koalastuff\.net\/llms\.txt"[^>]*>/g)];
if (llmsLinks.length !== 1) {
throw new Error(`Landing head must link exactly one canonical llms.txt document; found ${llmsLinks.length}`);
}
const requiredLlmsSections = [
'## Quick fit assessment',
'## How it works',
'## Privacy and security',
'## Supported environments',
'## Install KoalaSync',
'## Technical information'
];
for (const section of requiredLlmsSections) {
if (!llmsText.includes(section)) throw new Error(`llms.txt is missing ${section}`);
}
if (/\bWebRTC\b|\bport 54000\b|peer-to-peer by design/i.test(llmsText)) {
throw new Error('llms.txt must describe the current WebSocket relay architecture without obsolete WebRTC or port claims');
}
const documentedRelayUrls = [...llmsText.matchAll(/`(wss:\/\/[^`\s]+)`/g)].map(([, value]) => new URL(value));
const hasCanonicalPublicRelay = documentedRelayUrls.some((url) => (
url.protocol === 'wss:' &&
url.hostname === 'syncserver.koalastuff.net' &&
url.port === '' &&
url.pathname === '/' &&
url.search === '' &&
url.hash === ''
));
if (!hasCanonicalPublicRelay || !llmsText.includes('internally on port 3000')) {
throw new Error('llms.txt must distinguish the public TLS relay URL from the internal self-hosting port');
}
const selfHostingStart = template.indexOf('<div id="pane-docker"');
const selfHostingEnd = template.indexOf('</section>', selfHostingStart);
if (selfHostingStart === -1 || selfHostingEnd === -1) {
throw new Error('Could not locate the self-hosting examples in website/template.html');
}
const selfHostingExamples = template.slice(selfHostingStart, selfHostingEnd);
const requiredSelfHostingValues = [
'SERVER_SALT:',
'REPLACE_WITH_OPENSSL_RAND_BASE64_32_OUTPUT',
'ADMIN_METRICS_TOKEN:',
'DEBUG_LOGGING:',
'127.0.0.1:3000:3000'
];
for (const value of requiredSelfHostingValues) {
if (!selfHostingExamples.includes(value)) {
throw new Error(`Website self-hosting compose example is missing ${value}`);
}
}
if ((selfHostingExamples.match(/localhost:3000/g) || []).length !== 2 || selfHostingExamples.includes('KoalaSync:3000')) {
throw new Error('Both Caddy examples must match the compose loopback port binding');
}
const landingStylesheet = landingStylesheets[0][0];
if (!/href="\{\{ASSET_PATH\}\}landing\.min\.css"/.test(landingStylesheet)) {
throw new Error('Landing stylesheet must use the landing.min.css build placeholder');
}
if (/\bmedia=|data-(?:landing-)?deferred/.test(landingStylesheet)) {
throw new Error('Landing stylesheet must not be activated after first paint');
}
const runtimeCssActivation = [
['app.js', app],
['lang-init.js', langInit]
];
for (const [file, source] of runtimeCssActivation) {
if (/createElement\(['"]link['"]\)|requestIdleCallback|data-landing-deferred|data-deferred-css|\.media\s*=\s*['"]all['"]/.test(source)) {
throw new Error(`${file} must not dynamically load or activate structural CSS`);
}
}
// Film birds were removed entirely (commit 16cb138); guard against remnants
if (/film-hero-bird|film-bird-wing|film-birds/.test(template) || /filmBirdGlide|filmWingFlap/.test(demoCss)) {
throw new Error('Film birds were removed from the demo mockups; no bird markup or animations may remain');
}
const gettingStartedLightSurfaces = [
'step-illustration-1',
'step-illustration-2',
'step-illustration-3',
'illus-popup-card',
'illus-player-card',
'popup-select-mock'
];
for (const className of gettingStartedLightSurfaces) {
const pattern = new RegExp(`html\\.theme-light[^{]*\\.${className}[^}]*\\{`);
if (!pattern.test(landingPrimaryCss)) {
throw new Error(`Getting Started .${className} must define an explicit light-theme surface`);
}
}
const stepNumberLightRule = landingPrimaryCss.match(/html\.theme-light \.step-num\s*\{([^}]*)\}/)?.[1] || '';
if (!/color:\s*oklch\(/.test(stepNumberLightRule)
|| !/background:\s*none/.test(stepNumberLightRule)
|| !/-webkit-text-fill-color:\s*currentColor/.test(stepNumberLightRule)) {
throw new Error('Getting Started step numbers must use solid readable text in light mode');
}
if (!/class="footer-disclaimer"/.test(joinPage) || /footer-disclaimer[^>]*opacity:/.test(joinPage)) {
throw new Error('Join-page disclaimer must use the contrast-safe footer-disclaimer colors without opacity');
}
if (!/\.legal-inline-link\s*\{[^}]*text-decoration:\s*underline/s.test(legalCss)) {
throw new Error('Legal prose links must use a non-color underline cue');
}
for (const [name, page] of [['imprint.html', imprintPage], ['impressum-de.html', germanImprintPage]]) {
if ((page.match(/class="legal-inline-link"/g) || []).length !== 3) {
throw new Error(`${name} must mark all three prose links as legal-inline-link`);
}
if ((page.match(/class="legal-inline-label"/g) || []).length !== 2 || /opacity:\s*0\.6/.test(page)) {
throw new Error(`${name} contact labels must use full-opacity theme text`);
}
}
if (/<h3\b/.test(alternativesIndex)
|| (alternativesIndex.match(/<h2\b/g) || []).length !== 6
|| (alternativesIndex.match(/<h2[^>]+color:\s*var\(--text\)/g) || []).length !== 6) {
throw new Error('Alternatives overview cards must use h2 headings directly below the page h1');
}
if (!/html\.theme-light \.guide-card\s*\{[^}]*background-color:\s*var\(--card-surface\)\s*!important/s.test(alternativesCss)) {
throw new Error('Alternatives cards must define a readable light-theme surface');
}
const reducedMotionRule = demoCss.match(/@media \(prefers-reduced-motion: reduce\)\s*\{\s*\.step-illustration-3 \.film-mtn-scroll,\s*\.step-illustration-3 \.film-mid-scroll,\s*\.step-illustration-3 \.film-fore-scroll\s*\{([^}]*)\}/)?.[1] || '';
if (!/animation:\s*none\s*!important/.test(reducedMotionRule)) {
throw new Error('Getting Started film layers must stop when reduced motion is requested');
}
console.log('Extension mockup theme-sensitive text uses theme-aware colors');
console.log('Landing CSS is render-blocking, single-request, and cascade-stable');
console.log('Landing head discovers a complete and architecture-accurate llms.txt');
console.log('Website self-hosting examples include production secrets and consistent networking');
console.log('Foreground film birds use complete, always-on wing and glide animations');
console.log('All Getting Started mockups define explicit light-theme surfaces');
console.log('Getting Started step numbers stay readable in light mode');
console.log('Accessibility regressions stay fixed across legal, alternatives, and reduced-motion views');
+113
View File
@@ -0,0 +1,113 @@
/**
* KoalaSync Locale Translation Script
*
* This script is stored in `scripts/translate-locales-tool.cjs`
* so future LLM agents can easily reuse and adapt it to translate new keys.
*
* Usage:
* node scripts/translate-locales-tool.cjs
*/
const fs = require('fs');
const path = require('path');
const http = require('https');
const localesDir = path.join(__dirname, '../website/locales');
const enFile = path.join(localesDir, 'en.json');
const enLocale = JSON.parse(fs.readFileSync(enFile, 'utf8'));
// Keys starting with these prefixes need to be translated.
// Update this list when translating new pages or features.
const prefixes = ['ALT_W2G_', 'ALT_SCENER_', 'ALT_KOSMI_', 'ALT_TWOSEVEN_'];
const keysToTranslate = Object.keys(enLocale).filter(key => {
return prefixes.some(prefix => key.startsWith(prefix));
});
console.log(`Found ${keysToTranslate.length} keys to translate.`);
function translate(text, targetLang) {
return new Promise((resolve, reject) => {
// We use Google's free translation endpoint which is highly robust for standard text segment translations
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=en&tl=${targetLang}&dt=t&q=${encodeURIComponent(text)}`;
http.get(url, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => {
try {
const parsed = JSON.parse(data);
const translation = parsed[0].map(item => item[0]).join('');
resolve(translation);
} catch (_e) {
reject(new Error(`Failed to parse response for target ${targetLang}: ${data}`));
}
});
}).on('error', reject);
});
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const fileToLangMap = {
'es.json': 'es',
'fr.json': 'fr',
'it.json': 'it',
'ja.json': 'ja',
'ko.json': 'ko',
'nl.json': 'nl',
'pl.json': 'pl',
'pt-BR.json': 'pt',
'pt.json': 'pt',
'ru.json': 'ru',
'tr.json': 'tr',
'uk.json': 'uk',
'zh.json': 'zh-CN'
};
async function run() {
const files = fs.readdirSync(localesDir).filter(f => f.endsWith('.json') && f !== 'en.json' && f !== 'de.json');
for (const file of files) {
const targetLang = fileToLangMap[file];
if (!targetLang) {
console.log(`Skipping unknown file mapping: ${file}`);
continue;
}
const filePath = path.join(localesDir, file);
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
console.log(`\nTranslating ${file} (${targetLang})...`);
let translatedCount = 0;
for (const key of keysToTranslate) {
const englishValue = enLocale[key];
// Translate if missing or currently identical to English value (which means it's a fallback)
if (!content[key] || content[key] === englishValue) {
try {
const translatedValue = await translate(englishValue, targetLang);
content[key] = translatedValue;
translatedCount++;
console.log(` [${translatedCount}/${keysToTranslate.length}] Translated key: ${key}`);
await sleep(200); // 200ms delay to prevent rate limits
} catch (err) {
console.error(` Error translating key ${key} to ${targetLang}:`, err.message);
// Wait longer on error
await sleep(2000);
}
}
}
// Save back keeping exact same structure and format
fs.writeFileSync(filePath, JSON.stringify(content, null, 2) + '\n', 'utf8');
console.log(`Saved ${file} (${translatedCount} keys updated).`);
}
console.log('\nAll translations completed successfully!');
}
run().catch(err => {
console.error('Translation script failed:', err);
});
+50
View File
@@ -0,0 +1,50 @@
const fs = require('fs');
const path = require('path');
const localesDir = path.join(__dirname, '../website/locales');
const files = fs.readdirSync(localesDir).filter(f => f.endsWith('.json') && f !== 'en.json');
const brandTranslations = [
'dos siete', 'dos-siete', 'deux sept', 'deux-sept', 'zwei sieben', 'zwei-sieben',
'due sette', 'due-sette', 'dwa siedem', 'dwa-siedem', 'twee zeven', 'twee-zeven',
'iki yedi', 'iki-yedi', 'два семь', 'два-семь', '二七', '二 七', '이칠', '이 칠',
'koala sync', 'koala-sync', 'watch 2 gether', 'watch-2-gether', 'watch 2gether',
'watch-2gether', 'jelly fin', 'jelly-fin'
];
let failed = false;
for (const file of files) {
const filePath = path.join(localesDir, file);
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
for (const [key, value] of Object.entries(content)) {
if (typeof value !== 'string') continue;
// Check brand translations (case-insensitive)
const lowerValue = value.toLowerCase();
for (const pattern of brandTranslations) {
if (lowerValue.includes(pattern)) {
console.error(`Error in ${file} [key: ${key}]: Found translated brand pattern "${pattern}" in value: "${value}"`);
failed = true;
}
}
// Check tag validation
const tags = ['strong', 'em', 'span', 'b', 'i', 'p', 'a'];
for (const tag of tags) {
const openCount = (value.match(new RegExp(`<${tag}\\b[^>]*>`, 'g')) || []).length;
const closeCount = (value.match(new RegExp(`</${tag}\\b[^>]*>`, 'g')) || []).length;
if (openCount !== closeCount) {
console.error(`Error in ${file} [key: ${key}]: Unbalanced tag <${tag}> (open: ${openCount}, close: ${closeCount}) in value: "${value}"`);
failed = true;
}
}
}
}
if (!failed) {
console.log("All brand names and HTML tags are perfectly valid and intact across all languages!");
} else {
process.exit(1);
}
+5
View File
@@ -28,10 +28,15 @@ const checks = [
['background syntax', 'node', ['-c', 'extension/background.js']],
['locale coverage', 'node', ['scripts/test-locales.cjs']],
['website locale coverage', 'node', ['scripts/test-website-locales.mjs']],
['website theme coverage', 'node', ['scripts/test-website-theme.mjs']],
['lint', 'npm', ['run', 'lint']],
['root production audit', 'npm', ['audit', '--omit=dev']],
['server production audit', 'npm', ['audit', '--omit=dev'], { cwd: path.join(repoRoot, 'server') }],
['extension build', 'npm', ['run', 'build:extension']],
// Must run after the build: validates the exact artifact uploaded to AMO.
// --warnings-as-errors is required: addons-linter exits 0 on warnings, and AMO
// rejects on them, so without it this check would pass a rejectable build.
['AMO validation (firefox)', 'npx', ['addons-linter', '--warnings-as-errors', 'dist/koalasync-firefox.zip']],
['website build', 'node', ['website/build.cjs']]
];
+1 -1
View File
@@ -7,7 +7,7 @@
*/
export const PROTOCOL_VERSION = "1.0.0";
export const APP_VERSION = "2.5.3";
export const APP_VERSION = "2.6.0";
export const OFFICIAL_SERVER_URL = 'wss://syncserver.koalastuff.net';
export const OFFICIAL_LANDING_PAGE_URL = 'https://sync.koalastuff.net';
+146
View File
@@ -0,0 +1,146 @@
<!DOCTYPE html>
<html lang="en" class="lang-en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 Page Not Found | KoalaSync</title>
<!-- Absolute asset paths: Caddy rewrites any missing URL (also nested ones
like /foo/bar) to this file, so relative paths would break. -->
<link rel="preload" href="/style.min.css" as="style">
<link rel="stylesheet" href="/style.min.css">
<link rel="icon" type="image/webp" href="/assets/NewLogoIcon_64.webp">
<meta name="description" content="This page could not be found.">
<meta name="robots" content="noindex, follow">
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#10190e">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="/lang-init.min.js"></script>
</head>
<body>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="/" class="logo-area" style="text-decoration: none;">
<img src="/assets/NewLogoIcon_128.webp" alt="KoalaSync Logo" width="40" height="40">
<span>KoalaSync</span>
</a>
<div class="nav-links">
<a href="/" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="width: 16px; height: 16px; display: block;"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
<span>Home</span>
</a>
<a href="https://github.com/Shik3i/KoalaSync" target="_blank" rel="noopener" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" aria-hidden="true" style="display: block;"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
GitHub
</a>
</div>
</div>
</nav>
<main class="legal-content">
<div class="legal-card" data-reveal style="padding: 2.5rem 2rem; text-align: center;">
<div style="display: flex; justify-content: center;">
<img src="/assets/KoalaSearching-180.webp" srcset="/assets/KoalaSearching-180.webp 180w, /assets/KoalaSearching-360.webp 360w" sizes="180px" alt="A cute koala looking through a telescope, searching for the missing page" class="legal-mascot" width="180" height="180">
</div>
<h1 style="margin-bottom: 0.5rem;">404</h1>
<p style="text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem; border-bottom: 1px solid var(--glass-border); padding-bottom: 1.5rem; margin-bottom: 1.5rem;">
Page not found
</p>
<p style="max-width: 34rem; margin: 0 auto;">
This page wandered off into the bamboo forest. Our koala is still looking for it — in the meantime, head back to safety.
</p>
<div style="display: flex; justify-content: center; gap: 1rem; margin-top: 2rem; flex-wrap: wrap;">
<a href="/" class="btn btn-primary">
Back to home
</a>
<a href="https://github.com/Shik3i/KoalaSync/issues" target="_blank" rel="noopener" class="btn btn-secondary">
Report a broken link
</a>
</div>
</div>
</main>
<footer>
<div class="container">
<p>&copy; 2026 KoalaSync. Open source under the MIT License.</p>
<div style="margin-top: 1.5rem; font-size: 0.8rem; display: flex; justify-content: center; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<a href="/imprint" style="color: var(--text-muted); text-decoration: none;">Legal Notice</a>
<a href="/privacy" style="color: var(--text-muted); text-decoration: none;">Privacy Policy</a>
</div>
</div>
</footer>
<script src="/app.min.js"></script>
</body>
</html>
+15 -6
View File
@@ -4,11 +4,11 @@ This directory contains the static KoalaSync website. It is both the public mark
## Where You Are
- `template.html`, `style.css`, `app.js`, `lang-init.js`, and `locales/*.json` are source files.
- `template.html`, `style.css`, `styles/*.css`, `app.js`, `lang-init.js`, and `locales/*.json` are source files. `style.css` is the local-development manifest; production concatenates the modules in the order declared by `website/build.cjs`.
- `build.cjs` compiles the static site into `website/www/`.
- `website/www/` is generated output. Do not edit files there directly.
- `join.html` handles room-invite links and communicates with the extension through `bridge.js`.
- `llms.txt` gives crawlers and AI tools a compact project overview.
- `llms.txt` gives AI tools a detailed product profile and is linked from every localized landing-page `<head>`.
- `alternatives/` contains comparison pages for users evaluating KoalaSync against other watch-party approaches.
## Core Roles
@@ -33,9 +33,10 @@ The website is 100% static HTML, CSS, and JavaScript.
- **Static i18n compiler**: `build.cjs` combines `template.html` with dictionaries in `locales/`.
- **Build-time minification**: Source CSS/JS stays readable; generated output uses `.min.css` and `.min.js`.
- **Strangler CSS architecture**: `styles/*.css` supplies page-specific production bundles; `style.legacy.css` is the byte-identical, unloaded reference monolith. The landing bundle preserves the legacy cascade while excluding Join- and Alternatives-only rules. Structural CSS is not activated after paint because that causes layout shifts.
- **Zero backend**: The compiled site can be hosted by any static file server.
- **Zero external assets**: Fonts, icons, scripts, and images must remain self-hosted.
- **Generated SEO/runtime files**: `version.json`, sitemap, robots, clean URLs, localized pages, and minified assets are copied or generated into `www/`.
- **Generated SEO/runtime files**: `version.json`, `robots.txt`, `llms.txt`, clean URLs, localized pages, and minified assets are copied into `www/`; `sitemap.xml` is generated there from the current route set.
## Local Development & Compilation
@@ -54,8 +55,9 @@ Then open:
Focused verification:
```bash
node scripts/test-website-locales.mjs
node --check website/www/app.min.js
node --check website/www/lang-init.min.js
node scripts/test-website-theme.mjs
node --check website/app.js
node --check website/lang-init.js
```
Full verification:
@@ -75,6 +77,13 @@ sync.koalastuff.net {
file_server
encode zstd gzip
# Themed 404 page (Caddy returns an empty 404 without this)
handle_errors {
@notfound expression {err.status_code} == 404
rewrite @notfound /404.html
file_server
}
@static {
file
path *.ico *.css *.js *.png *.svg *.webp *.avif
@@ -98,4 +107,4 @@ sync.koalastuff.net {
- Do not add external CDNs, fonts, analytics, or third-party scripts.
- Keep invite credentials in the URL hash, not query parameters.
- Keep locale files synchronized with `website/build.cjs` and `scripts/test-website-locales.mjs`.
- Commit source changes and regenerated `www/` output together when website output changes.
- `website/www/` is gitignored build output. Commit the source changes only; rebuild `www/` locally or in CI for verification and deployment.
+121 -8
View File
@@ -65,6 +65,23 @@
}
</script>
<!-- Structured Data (Schema.org) for WebPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "{{ALT_INDEX_TITLE}}",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives",
"description": "{{ALT_INDEX_META_DESC}}",
"inLanguage": "{{LANG_CODE}}",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
}
}
</script>
<!-- Organization Schema -->
<script type="application/ld+json">
{
@@ -81,17 +98,80 @@
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="{{ASSET_PATH}}lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
@@ -152,7 +232,7 @@
<!-- Teleparty Card -->
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/teleparty" class="guide-card" style="text-decoration: none; background: rgba(255, 255, 255, 0.03); border: 1px solid var(--glass-border); border-radius: 12px; padding: 1.5rem; display: flex; flex-direction: column; justify-content: space-between;">
<div>
<h3 style="margin-top: 0; margin-bottom: 0.75rem; color: #fff; font-size: 1.25rem;">{{ALT_TELEPARTY_TITLE}}</h3>
<h2 style="margin-top: 0; margin-bottom: 0.75rem; color: var(--text); font-size: 1.25rem;">{{ALT_TELEPARTY_TITLE}}</h2>
<p style="font-size: 0.9rem; line-height: 1.5; color: var(--text-muted); margin-bottom: 1.5rem;">{{ALT_TELEPARTY_META_DESC}}</p>
</div>
<div class="btn btn-primary" style="align-self: flex-start; padding: 0.5rem 1rem; font-size: 0.85rem; border-radius: 6px;">
@@ -163,7 +243,7 @@
<!-- Watch2Gether Card -->
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/watch2gether" class="guide-card" style="text-decoration: none; background: rgba(255, 255, 255, 0.03); border: 1px solid var(--glass-border); border-radius: 12px; padding: 1.5rem; display: flex; flex-direction: column; justify-content: space-between;">
<div>
<h3 style="margin-top: 0; margin-bottom: 0.75rem; color: #fff; font-size: 1.25rem;">{{ALT_W2G_TITLE}}</h3>
<h2 style="margin-top: 0; margin-bottom: 0.75rem; color: var(--text); font-size: 1.25rem;">{{ALT_W2G_TITLE}}</h2>
<p style="font-size: 0.9rem; line-height: 1.5; color: var(--text-muted); margin-bottom: 1.5rem;">{{ALT_W2G_META_DESC}}</p>
</div>
<div class="btn btn-primary" style="align-self: flex-start; padding: 0.5rem 1rem; font-size: 0.85rem; border-radius: 6px;">
@@ -171,10 +251,43 @@
</div>
</a>
<!-- Scener Card -->
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/scener" class="guide-card" style="text-decoration: none; background: rgba(255, 255, 255, 0.03); border: 1px solid var(--glass-border); border-radius: 12px; padding: 1.5rem; display: flex; flex-direction: column; justify-content: space-between;">
<div>
<h2 style="margin-top: 0; margin-bottom: 0.75rem; color: var(--text); font-size: 1.25rem;">{{ALT_SCENER_TITLE}}</h2>
<p style="font-size: 0.9rem; line-height: 1.5; color: var(--text-muted); margin-bottom: 1.5rem;">{{ALT_SCENER_META_DESC}}</p>
</div>
<div class="btn btn-primary" style="align-self: flex-start; padding: 0.5rem 1rem; font-size: 0.85rem; border-radius: 6px;">
{{ALT_INDEX_READ_COMPARISON}}
</div>
</a>
<!-- Kosmi Card -->
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/kosmi" class="guide-card" style="text-decoration: none; background: rgba(255, 255, 255, 0.03); border: 1px solid var(--glass-border); border-radius: 12px; padding: 1.5rem; display: flex; flex-direction: column; justify-content: space-between;">
<div>
<h2 style="margin-top: 0; margin-bottom: 0.75rem; color: var(--text); font-size: 1.25rem;">{{ALT_KOSMI_TITLE}}</h2>
<p style="font-size: 0.9rem; line-height: 1.5; color: var(--text-muted); margin-bottom: 1.5rem;">{{ALT_KOSMI_META_DESC}}</p>
</div>
<div class="btn btn-primary" style="align-self: flex-start; padding: 0.5rem 1rem; font-size: 0.85rem; border-radius: 6px;">
{{ALT_INDEX_READ_COMPARISON}}
</div>
</a>
<!-- TwoSeven Card -->
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/twoseven" class="guide-card" style="text-decoration: none; background: rgba(255, 255, 255, 0.03); border: 1px solid var(--glass-border); border-radius: 12px; padding: 1.5rem; display: flex; flex-direction: column; justify-content: space-between;">
<div>
<h2 style="margin-top: 0; margin-bottom: 0.75rem; color: var(--text); font-size: 1.25rem;">{{ALT_TWOSEVEN_TITLE}}</h2>
<p style="font-size: 0.9rem; line-height: 1.5; color: var(--text-muted); margin-bottom: 1.5rem;">{{ALT_TWOSEVEN_META_DESC}}</p>
</div>
<div class="btn btn-primary" style="align-self: flex-start; padding: 0.5rem 1rem; font-size: 0.85rem; border-radius: 6px;">
{{ALT_INDEX_READ_COMPARISON}}
</div>
</a>
<!-- Screen Sharing Card -->
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/screen-sharing" class="guide-card" style="text-decoration: none; background: rgba(255, 255, 255, 0.03); border: 1px solid var(--glass-border); border-radius: 12px; padding: 1.5rem; display: flex; flex-direction: column; justify-content: space-between;">
<div>
<h3 style="margin-top: 0; margin-bottom: 0.75rem; color: #fff; font-size: 1.25rem;">{{ALT_SCREEN_TITLE}}</h3>
<h2 style="margin-top: 0; margin-bottom: 0.75rem; color: var(--text); font-size: 1.25rem;">{{ALT_SCREEN_TITLE}}</h2>
<p style="font-size: 0.9rem; line-height: 1.5; color: var(--text-muted); margin-bottom: 1.5rem;">{{ALT_SCREEN_META_DESC}}</p>
</div>
<div class="btn btn-primary" style="align-self: flex-start; padding: 0.5rem 1rem; font-size: 0.85rem; border-radius: 6px;">
+301
View File
@@ -0,0 +1,301 @@
<!DOCTYPE html>
<html lang="{{LANG_CODE}}" class="lang-{{LANG_CODE}}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ALT_KOSMI_TITLE}}</title>
<link rel="preload" href="{{ASSET_PATH}}style.min.css" as="style">
<link rel="stylesheet" href="{{ASSET_PATH}}style.min.css">
<link rel="icon" type="image/webp" href="{{ASSET_PATH}}assets/NewLogoIcon_64.webp">
<link rel="canonical" href="https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/kosmi">
<link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/kosmi">
<link rel="alternate" hreflang="de" href="https://sync.koalastuff.net/de/alternatives/kosmi">
<link rel="alternate" hreflang="fr" href="https://sync.koalastuff.net/fr/alternatives/kosmi">
<link rel="alternate" hreflang="es" href="https://sync.koalastuff.net/es/alternatives/kosmi">
<link rel="alternate" hreflang="pt-br" href="https://sync.koalastuff.net/pt-BR/alternatives/kosmi">
<link rel="alternate" hreflang="ru" href="https://sync.koalastuff.net/ru/alternatives/kosmi">
<link rel="alternate" hreflang="it" href="https://sync.koalastuff.net/it/alternatives/kosmi">
<link rel="alternate" hreflang="pl" href="https://sync.koalastuff.net/pl/alternatives/kosmi">
<link rel="alternate" hreflang="tr" href="https://sync.koalastuff.net/tr/alternatives/kosmi">
<link rel="alternate" hreflang="nl" href="https://sync.koalastuff.net/nl/alternatives/kosmi">
<link rel="alternate" hreflang="ja" href="https://sync.koalastuff.net/ja/alternatives/kosmi">
<link rel="alternate" hreflang="ko" href="https://sync.koalastuff.net/ko/alternatives/kosmi">
<link rel="alternate" hreflang="zh" href="https://sync.koalastuff.net/zh/alternatives/kosmi">
<link rel="alternate" hreflang="uk" href="https://sync.koalastuff.net/uk/alternatives/kosmi">
<link rel="alternate" hreflang="pt" href="https://sync.koalastuff.net/pt/alternatives/kosmi">
<link rel="alternate" hreflang="x-default" href="https://sync.koalastuff.net/alternatives/kosmi">
<meta name="description" content="{{ALT_KOSMI_META_DESC}}">
<meta name="robots" content="index, follow">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="article">
<meta property="og:url" content="https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/kosmi">
<meta property="og:title" content="{{ALT_KOSMI_TITLE}}">
<meta property="og:description" content="{{ALT_KOSMI_META_DESC}}">
<meta property="og:image" content="https://sync.koalastuff.net/assets/ProContraKoala.webp">
<meta property="og:locale" content="{{OG_LOCALE}}">
<!-- Twitter / X -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ALT_KOSMI_TITLE}}">
<meta name="twitter:description" content="{{ALT_KOSMI_META_DESC}}">
<meta name="twitter:image" content="https://sync.koalastuff.net/assets/ProContraKoala.webp">
<!-- Structured Data (Schema.org) for Breadcrumbs -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
},
{
"@type": "ListItem",
"position": 2,
"name": "Alternatives",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives"
},
{
"@type": "ListItem",
"position": 3,
"name": "KoalaSync vs Kosmi",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/kosmi"
}
]
}
</script>
<!-- Structured Data (Schema.org) for WebPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "{{ALT_KOSMI_TITLE}}",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/kosmi",
"description": "{{ALT_KOSMI_META_DESC}}",
"inLanguage": "{{LANG_CODE}}",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
}
}
</script>
<!-- Organization Schema -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/",
"logo": "https://sync.koalastuff.net/assets/NewLogoIcon_128.webp",
"sameAs": [
"https://github.com/Shik3i/KoalaSync",
"https://mastodon.social/@koalastuff"
]
}
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#10190e">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="{{ASSET_PATH}}lang-init.min.js"></script>
</head>
<body>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="{{ASSET_PATH}}" class="logo-area" style="text-decoration: none;">
<img src="{{ASSET_PATH}}assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="40" height="40">
<span>KoalaSync</span>
</a>
<div class="nav-links">
<a href="{{ASSET_PATH}}" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="width: 16px; height: 16px; display: block;"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
<span>Home</span>
</a>
<a href="https://github.com/Shik3i/KoalaSync" target="_blank" rel="noopener" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" aria-hidden="true" style="display: block;"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
GitHub
</a>
</div>
<div class="nav-right">
<div class="lang-select-container">
<select class="lang-dropdown" aria-label="Select Language">
<option value="en">🇬🇧 English</option>
<option value="de">🇩🇪 Deutsch</option>
<option value="fr">🇫🇷 Français</option>
<option value="es">🇪🇸 Español</option>
<option value="pt-BR">🇧🇷 Português (Brasil)</option>
<option value="ru">🇷🇺 Русский</option>
<option value="it">🇮🇹 Italiano</option>
<option value="pl">🇵🇱 Polski</option>
<option value="tr">🇹🇷 Türkçe</option>
<option value="nl">🇳🇱 Nederlands</option>
<option value="ja">🇯🇵 日本語</option>
<option value="ko">🇰🇷 한국어</option>
<option value="zh">🇨🇳 中文</option>
<option value="uk">🇺🇦 Українська</option>
<option value="pt">🇵🇹 Português (Portugal)</option>
</select>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="chevron-icon"><polyline points="6 9 12 15 18 9"/></svg>
</div>
<button class="hamburger" aria-label="Menu" aria-expanded="false"></button>
</div>
</div>
</nav>
<main class="legal-content">
<div class="legal-card" data-reveal style="padding: 2rem;">
<div style="display: flex; justify-content: center;">
<img src="{{ASSET_PATH}}assets/ProContraKoala.webp" alt="Koala weighing pros and cons" class="legal-mascot" width="180" height="180">
</div>
<h1>{{ALT_KOSMI_TITLE}}</h1>
<!-- Intro -->
<section>
<p><em>{{ALT_KOSMI_INTRO}}</em></p>
</section>
<!-- When Kosmi may still make sense -->
<section>
<h2>{{ALT_KOSMI_WHEN_KOSMI_TITLE}}</h2>
<p>{{ALT_KOSMI_WHEN_KOSMI_BODY}}</p>
</section>
<!-- When KoalaSync may fit better -->
<section>
<h2>{{ALT_KOSMI_WHEN_KOALA_TITLE}}</h2>
<p>{{ALT_KOSMI_WHEN_KOALA_BODY}}</p>
</section>
<!-- The main difference -->
<section>
<h2>{{ALT_KOSMI_MAIN_DIFF_TITLE}}</h2>
<p>{{ALT_KOSMI_MAIN_DIFF_BODY}}</p>
</section>
<!-- Honest limitations -->
<section>
<h2>{{ALT_KOSMI_LIMITS_TITLE}}</h2>
<p>{{ALT_KOSMI_LIMITS_BODY}}</p>
</section>
<!-- Summary -->
<section>
<h2>{{ALT_KOSMI_SUMMARY_TITLE}}</h2>
<p>{{ALT_KOSMI_SUMMARY_BODY}}</p>
</section>
<!-- CTA block -->
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--glass-border);">
<a href="{{ASSET_PATH}}" class="btn btn-primary" style="margin-bottom: 1.5rem;">{{ALT_TRY_KOALASYNC}}</a>
<p style="font-size: 0.9rem; text-align: center; display: flex; flex-direction: column; gap: 0.5rem;">
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/teleparty" style="color: var(--accent); text-decoration: none;">{{ALT_TELEPARTY_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/scener" style="color: var(--accent); text-decoration: none;">{{ALT_SCENER_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/twoseven" style="color: var(--accent); text-decoration: none;">{{ALT_TWOSEVEN_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/watch2gether" style="color: var(--accent); text-decoration: none;">{{ALT_W2G_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/screen-sharing" style="color: var(--accent); text-decoration: none;">{{ALT_SCREEN_TITLE}}</a>
</p>
</div>
</div>
</main>
<footer>
<div class="container">
<p>&copy; 2026 KoalaSync. {{FOOTER_MIT}}</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem;">{{FOOTER_RAM}}</p>
<div style="margin-top: 1.5rem; font-size: 0.8rem; display: flex; justify-content: center; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<a href="{{ASSET_PATH}}{{FOOTER_LEGAL_LINK}}">{{FOOTER_LEGAL}}</a>
<a href="{{ASSET_PATH}}{{FOOTER_PRIVACY_LINK}}">{{FOOTER_PRIVACY}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives"><span><span lang="en">Guides & comparisons</span><span lang="de">Vergleiche & Anleitungen</span></span></a>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" style="display: inline-flex; align-items: center; gap: 4px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="14" height="14" aria-hidden="true" style="display: block;"><path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z"/></svg>
Mastodon
</a>
</div>
</div>
</footer>
<script src="{{ASSET_PATH}}app.min.js"></script>
</body>
</html>
+301
View File
@@ -0,0 +1,301 @@
<!DOCTYPE html>
<html lang="{{LANG_CODE}}" class="lang-{{LANG_CODE}}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ALT_SCENER_TITLE}}</title>
<link rel="preload" href="{{ASSET_PATH}}style.min.css" as="style">
<link rel="stylesheet" href="{{ASSET_PATH}}style.min.css">
<link rel="icon" type="image/webp" href="{{ASSET_PATH}}assets/NewLogoIcon_64.webp">
<link rel="canonical" href="https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/scener">
<link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/scener">
<link rel="alternate" hreflang="de" href="https://sync.koalastuff.net/de/alternatives/scener">
<link rel="alternate" hreflang="fr" href="https://sync.koalastuff.net/fr/alternatives/scener">
<link rel="alternate" hreflang="es" href="https://sync.koalastuff.net/es/alternatives/scener">
<link rel="alternate" hreflang="pt-br" href="https://sync.koalastuff.net/pt-BR/alternatives/scener">
<link rel="alternate" hreflang="ru" href="https://sync.koalastuff.net/ru/alternatives/scener">
<link rel="alternate" hreflang="it" href="https://sync.koalastuff.net/it/alternatives/scener">
<link rel="alternate" hreflang="pl" href="https://sync.koalastuff.net/pl/alternatives/scener">
<link rel="alternate" hreflang="tr" href="https://sync.koalastuff.net/tr/alternatives/scener">
<link rel="alternate" hreflang="nl" href="https://sync.koalastuff.net/nl/alternatives/scener">
<link rel="alternate" hreflang="ja" href="https://sync.koalastuff.net/ja/alternatives/scener">
<link rel="alternate" hreflang="ko" href="https://sync.koalastuff.net/ko/alternatives/scener">
<link rel="alternate" hreflang="zh" href="https://sync.koalastuff.net/zh/alternatives/scener">
<link rel="alternate" hreflang="uk" href="https://sync.koalastuff.net/uk/alternatives/scener">
<link rel="alternate" hreflang="pt" href="https://sync.koalastuff.net/pt/alternatives/scener">
<link rel="alternate" hreflang="x-default" href="https://sync.koalastuff.net/alternatives/scener">
<meta name="description" content="{{ALT_SCENER_META_DESC}}">
<meta name="robots" content="index, follow">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="article">
<meta property="og:url" content="https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/scener">
<meta property="og:title" content="{{ALT_SCENER_TITLE}}">
<meta property="og:description" content="{{ALT_SCENER_META_DESC}}">
<meta property="og:image" content="https://sync.koalastuff.net/assets/ProContraKoala.webp">
<meta property="og:locale" content="{{OG_LOCALE}}">
<!-- Twitter / X -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ALT_SCENER_TITLE}}">
<meta name="twitter:description" content="{{ALT_SCENER_META_DESC}}">
<meta name="twitter:image" content="https://sync.koalastuff.net/assets/ProContraKoala.webp">
<!-- Structured Data (Schema.org) for Breadcrumbs -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
},
{
"@type": "ListItem",
"position": 2,
"name": "Alternatives",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives"
},
{
"@type": "ListItem",
"position": 3,
"name": "KoalaSync vs Scener",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/scener"
}
]
}
</script>
<!-- Structured Data (Schema.org) for WebPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "{{ALT_SCENER_TITLE}}",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/scener",
"description": "{{ALT_SCENER_META_DESC}}",
"inLanguage": "{{LANG_CODE}}",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
}
}
</script>
<!-- Organization Schema -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/",
"logo": "https://sync.koalastuff.net/assets/NewLogoIcon_128.webp",
"sameAs": [
"https://github.com/Shik3i/KoalaSync",
"https://mastodon.social/@koalastuff"
]
}
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#10190e">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="{{ASSET_PATH}}lang-init.min.js"></script>
</head>
<body>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="{{ASSET_PATH}}" class="logo-area" style="text-decoration: none;">
<img src="{{ASSET_PATH}}assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="40" height="40">
<span>KoalaSync</span>
</a>
<div class="nav-links">
<a href="{{ASSET_PATH}}" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="width: 16px; height: 16px; display: block;"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
<span>Home</span>
</a>
<a href="https://github.com/Shik3i/KoalaSync" target="_blank" rel="noopener" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" aria-hidden="true" style="display: block;"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
GitHub
</a>
</div>
<div class="nav-right">
<div class="lang-select-container">
<select class="lang-dropdown" aria-label="Select Language">
<option value="en">🇬🇧 English</option>
<option value="de">🇩🇪 Deutsch</option>
<option value="fr">🇫🇷 Français</option>
<option value="es">🇪🇸 Español</option>
<option value="pt-BR">🇧🇷 Português (Brasil)</option>
<option value="ru">🇷🇺 Русский</option>
<option value="it">🇮🇹 Italiano</option>
<option value="pl">🇵🇱 Polski</option>
<option value="tr">🇹🇷 Türkçe</option>
<option value="nl">🇳🇱 Nederlands</option>
<option value="ja">🇯🇵 日本語</option>
<option value="ko">🇰🇷 한국어</option>
<option value="zh">🇨🇳 中文</option>
<option value="uk">🇺🇦 Українська</option>
<option value="pt">🇵🇹 Português (Portugal)</option>
</select>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="chevron-icon"><polyline points="6 9 12 15 18 9"/></svg>
</div>
<button class="hamburger" aria-label="Menu" aria-expanded="false"></button>
</div>
</div>
</nav>
<main class="legal-content">
<div class="legal-card" data-reveal style="padding: 2rem;">
<div style="display: flex; justify-content: center;">
<img src="{{ASSET_PATH}}assets/ProContraKoala.webp" alt="Koala weighing pros and cons" class="legal-mascot" width="180" height="180">
</div>
<h1>{{ALT_SCENER_TITLE}}</h1>
<!-- Intro -->
<section>
<p><em>{{ALT_SCENER_INTRO}}</em></p>
</section>
<!-- When Scener may still make sense -->
<section>
<h2>{{ALT_SCENER_WHEN_SCENER_TITLE}}</h2>
<p>{{ALT_SCENER_WHEN_SCENER_BODY}}</p>
</section>
<!-- When KoalaSync may fit better -->
<section>
<h2>{{ALT_SCENER_WHEN_KOALA_TITLE}}</h2>
<p>{{ALT_SCENER_WHEN_KOALA_BODY}}</p>
</section>
<!-- The main difference -->
<section>
<h2>{{ALT_SCENER_MAIN_DIFF_TITLE}}</h2>
<p>{{ALT_SCENER_MAIN_DIFF_BODY}}</p>
</section>
<!-- Honest limitations -->
<section>
<h2>{{ALT_SCENER_LIMITS_TITLE}}</h2>
<p>{{ALT_SCENER_LIMITS_BODY}}</p>
</section>
<!-- Summary -->
<section>
<h2>{{ALT_SCENER_SUMMARY_TITLE}}</h2>
<p>{{ALT_SCENER_SUMMARY_BODY}}</p>
</section>
<!-- CTA block -->
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--glass-border);">
<a href="{{ASSET_PATH}}" class="btn btn-primary" style="margin-bottom: 1.5rem;">{{ALT_TRY_KOALASYNC}}</a>
<p style="font-size: 0.9rem; text-align: center; display: flex; flex-direction: column; gap: 0.5rem;">
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/kosmi" style="color: var(--accent); text-decoration: none;">{{ALT_KOSMI_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/twoseven" style="color: var(--accent); text-decoration: none;">{{ALT_TWOSEVEN_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/teleparty" style="color: var(--accent); text-decoration: none;">{{ALT_TELEPARTY_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/watch2gether" style="color: var(--accent); text-decoration: none;">{{ALT_W2G_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/screen-sharing" style="color: var(--accent); text-decoration: none;">{{ALT_SCREEN_TITLE}}</a>
</p>
</div>
</div>
</main>
<footer>
<div class="container">
<p>&copy; 2026 KoalaSync. {{FOOTER_MIT}}</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem;">{{FOOTER_RAM}}</p>
<div style="margin-top: 1.5rem; font-size: 0.8rem; display: flex; justify-content: center; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<a href="{{ASSET_PATH}}{{FOOTER_LEGAL_LINK}}">{{FOOTER_LEGAL}}</a>
<a href="{{ASSET_PATH}}{{FOOTER_PRIVACY_LINK}}">{{FOOTER_PRIVACY}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives"><span><span lang="en">Guides & comparisons</span><span lang="de">Vergleiche & Anleitungen</span></span></a>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" style="display: inline-flex; align-items: center; gap: 4px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="14" height="14" aria-hidden="true" style="display: block;"><path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z"/></svg>
Mastodon
</a>
</div>
</div>
</footer>
<script src="{{ASSET_PATH}}app.min.js"></script>
</body>
</html>
+88 -5
View File
@@ -71,6 +71,23 @@
}
</script>
<!-- Structured Data (Schema.org) for WebPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "{{ALT_SCREEN_TITLE}}",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/screen-sharing",
"description": "{{ALT_SCREEN_META_DESC}}",
"inLanguage": "{{LANG_CODE}}",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
}
}
</script>
<!-- Organization Schema -->
<script type="application/ld+json">
{
@@ -87,17 +104,80 @@
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="{{ASSET_PATH}}lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
@@ -190,6 +270,9 @@
<a href="{{ASSET_PATH}}" class="btn btn-primary" style="margin-bottom: 1.5rem;">{{ALT_TRY_KOALASYNC}}</a>
<p style="font-size: 0.9rem; text-align: center; display: flex; flex-direction: column; gap: 0.5rem;">
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/watch2gether" style="color: var(--accent); text-decoration: none;">{{ALT_W2G_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/scener" style="color: var(--accent); text-decoration: none;">{{ALT_SCENER_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/kosmi" style="color: var(--accent); text-decoration: none;">{{ALT_KOSMI_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/twoseven" style="color: var(--accent); text-decoration: none;">{{ALT_TWOSEVEN_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/teleparty" style="color: var(--accent); text-decoration: none;">{{ALT_TELEPARTY_TITLE}}</a>
</p>
</div>
+88 -5
View File
@@ -71,6 +71,23 @@
}
</script>
<!-- Structured Data (Schema.org) for WebPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "{{ALT_TELEPARTY_TITLE}}",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/teleparty",
"description": "{{ALT_TELEPARTY_META_DESC}}",
"inLanguage": "{{LANG_CODE}}",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
}
}
</script>
<!-- Organization Schema -->
<script type="application/ld+json">
{
@@ -87,17 +104,80 @@
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="{{ASSET_PATH}}lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
@@ -190,6 +270,9 @@
<a href="{{ASSET_PATH}}" class="btn btn-primary" style="margin-bottom: 1.5rem;">{{ALT_TRY_KOALASYNC}}</a>
<p style="font-size: 0.9rem; text-align: center; display: flex; flex-direction: column; gap: 0.5rem;">
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/watch2gether" style="color: var(--accent); text-decoration: none;">{{ALT_W2G_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/scener" style="color: var(--accent); text-decoration: none;">{{ALT_SCENER_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/kosmi" style="color: var(--accent); text-decoration: none;">{{ALT_KOSMI_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/twoseven" style="color: var(--accent); text-decoration: none;">{{ALT_TWOSEVEN_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/screen-sharing" style="color: var(--accent); text-decoration: none;">{{ALT_SCREEN_TITLE}}</a>
</p>
</div>
+301
View File
@@ -0,0 +1,301 @@
<!DOCTYPE html>
<html lang="{{LANG_CODE}}" class="lang-{{LANG_CODE}}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ALT_TWOSEVEN_TITLE}}</title>
<link rel="preload" href="{{ASSET_PATH}}style.min.css" as="style">
<link rel="stylesheet" href="{{ASSET_PATH}}style.min.css">
<link rel="icon" type="image/webp" href="{{ASSET_PATH}}assets/NewLogoIcon_64.webp">
<link rel="canonical" href="https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/twoseven">
<link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/twoseven">
<link rel="alternate" hreflang="de" href="https://sync.koalastuff.net/de/alternatives/twoseven">
<link rel="alternate" hreflang="fr" href="https://sync.koalastuff.net/fr/alternatives/twoseven">
<link rel="alternate" hreflang="es" href="https://sync.koalastuff.net/es/alternatives/twoseven">
<link rel="alternate" hreflang="pt-br" href="https://sync.koalastuff.net/pt-BR/alternatives/twoseven">
<link rel="alternate" hreflang="ru" href="https://sync.koalastuff.net/ru/alternatives/twoseven">
<link rel="alternate" hreflang="it" href="https://sync.koalastuff.net/it/alternatives/twoseven">
<link rel="alternate" hreflang="pl" href="https://sync.koalastuff.net/pl/alternatives/twoseven">
<link rel="alternate" hreflang="tr" href="https://sync.koalastuff.net/tr/alternatives/twoseven">
<link rel="alternate" hreflang="nl" href="https://sync.koalastuff.net/nl/alternatives/twoseven">
<link rel="alternate" hreflang="ja" href="https://sync.koalastuff.net/ja/alternatives/twoseven">
<link rel="alternate" hreflang="ko" href="https://sync.koalastuff.net/ko/alternatives/twoseven">
<link rel="alternate" hreflang="zh" href="https://sync.koalastuff.net/zh/alternatives/twoseven">
<link rel="alternate" hreflang="uk" href="https://sync.koalastuff.net/uk/alternatives/twoseven">
<link rel="alternate" hreflang="pt" href="https://sync.koalastuff.net/pt/alternatives/twoseven">
<link rel="alternate" hreflang="x-default" href="https://sync.koalastuff.net/alternatives/twoseven">
<meta name="description" content="{{ALT_TWOSEVEN_META_DESC}}">
<meta name="robots" content="index, follow">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="article">
<meta property="og:url" content="https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/twoseven">
<meta property="og:title" content="{{ALT_TWOSEVEN_TITLE}}">
<meta property="og:description" content="{{ALT_TWOSEVEN_META_DESC}}">
<meta property="og:image" content="https://sync.koalastuff.net/assets/ProContraKoala.webp">
<meta property="og:locale" content="{{OG_LOCALE}}">
<!-- Twitter / X -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ALT_TWOSEVEN_TITLE}}">
<meta name="twitter:description" content="{{ALT_TWOSEVEN_META_DESC}}">
<meta name="twitter:image" content="https://sync.koalastuff.net/assets/ProContraKoala.webp">
<!-- Structured Data (Schema.org) for Breadcrumbs -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
},
{
"@type": "ListItem",
"position": 2,
"name": "Alternatives",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives"
},
{
"@type": "ListItem",
"position": 3,
"name": "KoalaSync vs TwoSeven",
"item": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/twoseven"
}
]
}
</script>
<!-- Structured Data (Schema.org) for WebPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "{{ALT_TWOSEVEN_TITLE}}",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/twoseven",
"description": "{{ALT_TWOSEVEN_META_DESC}}",
"inLanguage": "{{LANG_CODE}}",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
}
}
</script>
<!-- Organization Schema -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/",
"logo": "https://sync.koalastuff.net/assets/NewLogoIcon_128.webp",
"sameAs": [
"https://github.com/Shik3i/KoalaSync",
"https://mastodon.social/@koalastuff"
]
}
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#10190e">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="{{ASSET_PATH}}lang-init.min.js"></script>
</head>
<body>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="{{ASSET_PATH}}" class="logo-area" style="text-decoration: none;">
<img src="{{ASSET_PATH}}assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="40" height="40">
<span>KoalaSync</span>
</a>
<div class="nav-links">
<a href="{{ASSET_PATH}}" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="width: 16px; height: 16px; display: block;"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
<span>Home</span>
</a>
<a href="https://github.com/Shik3i/KoalaSync" target="_blank" rel="noopener" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" aria-hidden="true" style="display: block;"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
GitHub
</a>
</div>
<div class="nav-right">
<div class="lang-select-container">
<select class="lang-dropdown" aria-label="Select Language">
<option value="en">🇬🇧 English</option>
<option value="de">🇩🇪 Deutsch</option>
<option value="fr">🇫🇷 Français</option>
<option value="es">🇪🇸 Español</option>
<option value="pt-BR">🇧🇷 Português (Brasil)</option>
<option value="ru">🇷🇺 Русский</option>
<option value="it">🇮🇹 Italiano</option>
<option value="pl">🇵🇱 Polski</option>
<option value="tr">🇹🇷 Türkçe</option>
<option value="nl">🇳🇱 Nederlands</option>
<option value="ja">🇯🇵 日本語</option>
<option value="ko">🇰🇷 한국어</option>
<option value="zh">🇨🇳 中文</option>
<option value="uk">🇺🇦 Українська</option>
<option value="pt">🇵🇹 Português (Portugal)</option>
</select>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="chevron-icon"><polyline points="6 9 12 15 18 9"/></svg>
</div>
<button class="hamburger" aria-label="Menu" aria-expanded="false"></button>
</div>
</div>
</nav>
<main class="legal-content">
<div class="legal-card" data-reveal style="padding: 2rem;">
<div style="display: flex; justify-content: center;">
<img src="{{ASSET_PATH}}assets/ProContraKoala.webp" alt="Koala weighing pros and cons" class="legal-mascot" width="180" height="180">
</div>
<h1>{{ALT_TWOSEVEN_TITLE}}</h1>
<!-- Intro -->
<section>
<p><em>{{ALT_TWOSEVEN_INTRO}}</em></p>
</section>
<!-- When TwoSeven may still make sense -->
<section>
<h2>{{ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE}}</h2>
<p>{{ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY}}</p>
</section>
<!-- When KoalaSync may fit better -->
<section>
<h2>{{ALT_TWOSEVEN_WHEN_KOALA_TITLE}}</h2>
<p>{{ALT_TWOSEVEN_WHEN_KOALA_BODY}}</p>
</section>
<!-- The main difference -->
<section>
<h2>{{ALT_TWOSEVEN_MAIN_DIFF_TITLE}}</h2>
<p>{{ALT_TWOSEVEN_MAIN_DIFF_BODY}}</p>
</section>
<!-- Honest limitations -->
<section>
<h2>{{ALT_TWOSEVEN_LIMITS_TITLE}}</h2>
<p>{{ALT_TWOSEVEN_LIMITS_BODY}}</p>
</section>
<!-- Summary -->
<section>
<h2>{{ALT_TWOSEVEN_SUMMARY_TITLE}}</h2>
<p>{{ALT_TWOSEVEN_SUMMARY_BODY}}</p>
</section>
<!-- CTA block -->
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--glass-border);">
<a href="{{ASSET_PATH}}" class="btn btn-primary" style="margin-bottom: 1.5rem;">{{ALT_TRY_KOALASYNC}}</a>
<p style="font-size: 0.9rem; text-align: center; display: flex; flex-direction: column; gap: 0.5rem;">
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/teleparty" style="color: var(--accent); text-decoration: none;">{{ALT_TELEPARTY_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/scener" style="color: var(--accent); text-decoration: none;">{{ALT_SCENER_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/kosmi" style="color: var(--accent); text-decoration: none;">{{ALT_KOSMI_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/watch2gether" style="color: var(--accent); text-decoration: none;">{{ALT_W2G_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/screen-sharing" style="color: var(--accent); text-decoration: none;">{{ALT_SCREEN_TITLE}}</a>
</p>
</div>
</div>
</main>
<footer>
<div class="container">
<p>&copy; 2026 KoalaSync. {{FOOTER_MIT}}</p>
<p style="font-size: 0.8rem; margin-top: 0.5rem;">{{FOOTER_RAM}}</p>
<div style="margin-top: 1.5rem; font-size: 0.8rem; display: flex; justify-content: center; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<a href="{{ASSET_PATH}}{{FOOTER_LEGAL_LINK}}">{{FOOTER_LEGAL}}</a>
<a href="{{ASSET_PATH}}{{FOOTER_PRIVACY_LINK}}">{{FOOTER_PRIVACY}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives"><span><span lang="en">Guides & comparisons</span><span lang="de">Vergleiche & Anleitungen</span></span></a>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" style="display: inline-flex; align-items: center; gap: 4px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="14" height="14" aria-hidden="true" style="display: block;"><path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z"/></svg>
Mastodon
</a>
</div>
</div>
</footer>
<script src="{{ASSET_PATH}}app.min.js"></script>
</body>
</html>
+88 -5
View File
@@ -71,6 +71,23 @@
}
</script>
<!-- Structured Data (Schema.org) for WebPage -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "{{ALT_W2G_TITLE}}",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}alternatives/watch2gether",
"description": "{{ALT_W2G_META_DESC}}",
"inLanguage": "{{LANG_CODE}}",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/{{LANG_PREFIX}}"
}
}
</script>
<!-- Organization Schema -->
<script type="application/ld+json">
{
@@ -87,17 +104,80 @@
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="{{ASSET_PATH}}lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
@@ -189,6 +269,9 @@
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid var(--glass-border);">
<a href="{{ASSET_PATH}}" class="btn btn-primary" style="margin-bottom: 1.5rem;">{{ALT_TRY_KOALASYNC}}</a>
<p style="font-size: 0.9rem; text-align: center; display: flex; flex-direction: column; gap: 0.5rem;">
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/scener" style="color: var(--accent); text-decoration: none;">{{ALT_SCENER_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/kosmi" style="color: var(--accent); text-decoration: none;">{{ALT_KOSMI_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/twoseven" style="color: var(--accent); text-decoration: none;">{{ALT_TWOSEVEN_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/teleparty" style="color: var(--accent); text-decoration: none;">{{ALT_TELEPARTY_TITLE}}</a>
<a href="{{ASSET_PATH}}{{LANG_PREFIX}}alternatives/screen-sharing" style="color: var(--accent); text-decoration: none;">{{ALT_SCREEN_TITLE}}</a>
</p>
+254 -46
View File
@@ -60,32 +60,73 @@ document.addEventListener('DOMContentLoaded', () => {
}
};
// Theme toggle (dark is default; light mode via html.theme-light,
const restartAnimation = (el, className) => {
if (!el) return;
el.classList.remove(className);
requestAnimationFrame(() => {
requestAnimationFrame(() => {
el.classList.add(className);
});
});
};
// Populated by the forest renderer further down (no-op until then)
let forestGreet = null;
// Theme toggle (saved preference wins; otherwise follows system preference,
// pre-paint class is applied by lang-init.js to avoid a flash)
const themeToggle = document.getElementById('theme-toggle');
const themeMeta = document.querySelector('meta[name="theme-color"]');
const themeStorageKey = 'koala_theme';
const systemThemeQuery = (() => {
try {
return window.matchMedia ? window.matchMedia('(prefers-color-scheme: light)') : null;
} catch (_) {
return null;
}
})();
const getSystemTheme = () => systemThemeQuery && systemThemeQuery.matches ? 'light' : 'dark';
const getSavedTheme = () => {
const savedTheme = safeGetLocalStorage(themeStorageKey);
return savedTheme === 'light' || savedTheme === 'dark' ? savedTheme : null;
};
const getCurrentTheme = () => document.documentElement.classList.contains('theme-light') ? 'light' : 'dark';
const savedTheme = safeGetLocalStorage(themeStorageKey);
const applyTheme = (theme) => {
document.documentElement.classList.toggle('theme-light', theme === 'light');
};
if (savedTheme === 'light') {
document.documentElement.classList.add('theme-light');
} else if (savedTheme === 'dark') {
document.documentElement.classList.remove('theme-light');
}
applyTheme(getSavedTheme() || getSystemTheme());
const syncThemeMeta = () => {
if (themeMeta) {
themeMeta.setAttribute('content', document.documentElement.classList.contains('theme-light') ? '#f1f5f9' : '#0f172a');
themeMeta.setAttribute('content', document.documentElement.classList.contains('theme-light') ? '#f0efe7' : '#10190e');
}
};
syncThemeMeta();
safeSetLocalStorage(themeStorageKey, getCurrentTheme());
const syncSystemTheme = () => {
if (getSavedTheme()) return;
applyTheme(getSystemTheme());
syncThemeMeta();
};
if (systemThemeQuery) {
if (typeof systemThemeQuery.addEventListener === 'function') {
systemThemeQuery.addEventListener('change', syncSystemTheme);
} else if (typeof systemThemeQuery.addListener === 'function') {
systemThemeQuery.addListener(syncSystemTheme);
}
}
if (themeToggle) {
themeToggle.addEventListener('click', () => {
const isLight = document.documentElement.classList.toggle('theme-light');
safeSetLocalStorage(themeStorageKey, isLight ? 'light' : 'dark');
const nextTheme = getCurrentTheme() === 'light' ? 'dark' : 'light';
applyTheme(nextTheme);
safeSetLocalStorage(themeStorageKey, nextTheme);
syncThemeMeta();
// Switching into light mode flares the horizon once (sunrise)
const scene = document.querySelector('.bg-nature');
if (nextTheme === 'light' && scene && !window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
restartAnimation(scene, 'sunrise');
setTimeout(() => scene.classList.remove('sunrise'), 1700);
}
});
}
@@ -129,7 +170,6 @@ document.addEventListener('DOMContentLoaded', () => {
};
const scheduleHeroMascotAnchor = () => requestAnimationFrame(syncHeroMascotAnchor);
scheduleHeroMascotAnchor();
window.addEventListener('load', scheduleHeroMascotAnchor, { once: true });
window.addEventListener('resize', scheduleHeroMascotAnchor, { passive: true });
if ('ResizeObserver' in window) {
@@ -152,6 +192,19 @@ document.addEventListener('DOMContentLoaded', () => {
// Scroll Reveal Logic (IntersectionObserver for performance)
const revealElements = document.querySelectorAll('[data-reveal]');
// Hash navigation must never land on an intentionally transparent state.
// Reveal the destination before the smooth scroll begins; the observer
// continues to animate sections reached through ordinary scrolling.
const revealHashTarget = () => {
const id = decodeURIComponent(window.location.hash.slice(1));
const target = id ? document.getElementById(id) : null;
if (!target) return;
if (target.matches('[data-reveal]')) target.classList.add('revealed');
target.querySelectorAll('[data-reveal]').forEach(el => el.classList.add('revealed'));
};
revealHashTarget();
window.addEventListener('hashchange', revealHashTarget);
if ('IntersectionObserver' in window) {
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
@@ -161,7 +214,7 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
}, {
rootMargin: '0px 0px -30px 0px',
rootMargin: '0px 0px 12% 0px',
threshold: 0.05
});
@@ -178,7 +231,12 @@ document.addEventListener('DOMContentLoaded', () => {
const sectionObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
history.replaceState(null, null, '#' + entry.target.id);
if (entry.target.id === 'top') {
history.replaceState(null, null, window.location.pathname + window.location.search);
} else {
history.replaceState(null, null, '#' + entry.target.id);
}
if (forestGreet) forestGreet();
}
});
}, { threshold: 0.3 });
@@ -191,6 +249,152 @@ document.addEventListener('DOMContentLoaded', () => {
nav.classList.toggle('nav-scrolled', window.scrollY > 50);
}, { passive: true });
// Bamboo forest: scroll journey + parallax (background layers only).
// The vertical drift maps scroll PROGRESS (0..1 over the whole page) onto
// the stalks' 20% overscan, so the parallax runs for the entire scroll
// instead of saturating after a few hundred pixels. The same progress
// value crossfades the scene from sunlit canopy into misty dusk, and on
// pointer devices the layers tilt slightly toward the cursor.
const bambooFar = document.getElementById('bamboo-far');
const bambooMid = document.getElementById('bamboo-mid');
const bambooNear = document.getElementById('bamboo-near');
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (bambooFar && bambooNear && !prefersReducedMotion) {
const depthDay = document.querySelector('.bg-depth-day');
const fireflies = Array.from(document.querySelectorAll('.firefly-wrap'), (el) => ({ el, x: 0, y: 0 }));
const canHover = window.matchMedia('(hover: hover)').matches;
let mouseX = 0;
let mouseY = 0;
let pointerX = -9999;
let pointerY = -9999;
let framePending = false;
const renderForest = () => {
framePending = false;
bambooFar.style.transform = `translateX(${(-mouseX * 5).toFixed(1)}px)`;
bambooNear.style.transform = `translateX(${(mouseX * 11).toFixed(1)}px)`;
if (bambooMid) bambooMid.style.transform = `translateX(${(mouseX * 4).toFixed(1)}px)`;
if (depthDay) depthDay.style.transform = `translate(${(-mouseX * 2.5).toFixed(1)}px, ${(mouseY * 1.5).toFixed(1)}px)`;
// Fireflies shy away from the cursor and drift back once it leaves
let settling = false;
for (const fly of fireflies) {
const cx = fly.el.offsetLeft + 2;
const cy = fly.el.offsetTop + 2;
const dx = cx - pointerX;
const dy = cy - pointerY;
const dist = Math.hypot(dx, dy);
let tx = 0;
let ty = 0;
if (dist < 130 && dist > 0.001) {
const push = ((130 - dist) / 130) * 46;
tx = (dx / dist) * push;
ty = (dy / dist) * push;
}
fly.x += (tx - fly.x) * 0.14;
fly.y += (ty - fly.y) * 0.14;
if (Math.abs(tx - fly.x) > 0.4 || Math.abs(ty - fly.y) > 0.4) settling = true;
fly.el.style.transform = `translate(${fly.x.toFixed(1)}px, ${fly.y.toFixed(1)}px)`;
}
if (settling) requestForestFrame();
};
const requestForestFrame = () => {
if (!framePending) {
framePending = true;
requestAnimationFrame(renderForest);
}
};
// Let one firefly greet newly reached sections (used by the section
// observer below; index rotates so it is not always the same one)
let helloIndex = 0;
forestGreet = () => {
if (!fireflies.length) return;
const wrap = fireflies[helloIndex % fireflies.length].el;
helloIndex += 1;
restartAnimation(wrap, 'firefly-hello');
setTimeout(() => wrap.classList.remove('firefly-hello'), 1300);
};
window.addEventListener('resize', requestForestFrame, { passive: true });
if (canHover) {
window.addEventListener('pointermove', (e) => {
mouseX = (e.clientX / window.innerWidth - 0.5) * 2;
mouseY = (e.clientY / window.innerHeight - 0.5) * 2;
pointerX = e.clientX;
pointerY = e.clientY;
requestForestFrame();
}, { passive: true });
window.addEventListener('pointerleave', () => {
pointerX = -9999;
pointerY = -9999;
requestForestFrame();
});
}
renderForest();
}
// Eucalyptus click confetti: leaves burst from wherever the visitor
// presses. Buttons and other controls shed leaves along their whole
// width; anywhere else a small fan rises from the pointer itself. The
// hero walkthrough's scripted cursor calls burstFromElement directly so
// its fake clicks scatter leaves too. Rate-capped, pointer-events:none —
// it can never block a click or flood the DOM.
let burstFromElement = () => {};
if (!prefersReducedMotion) {
const spawnLeaf = (x, y) => {
const leaf = document.createElement('span');
// Three tones of the palette: deep green, sage, a dash of amber
const tone = Math.random();
leaf.className = 'click-leaf' + (tone < 0.25 ? ' click-leaf-amber' : tone < 0.55 ? ' click-leaf-sage' : '');
// Fan out upward to a burst peak; the keyframes brake there and
// let the leaf sink past it while the inner element rocks.
const angle = (-90 + (Math.random() - 0.5) * 150) * Math.PI / 180;
const dist = 26 + Math.random() * 38;
const dur = 0.9 + Math.random() * 0.5;
leaf.style.left = x + 'px';
leaf.style.top = y + 'px';
leaf.style.setProperty('--leaf-x', (Math.cos(angle) * dist).toFixed(1) + 'px');
leaf.style.setProperty('--leaf-y', (Math.sin(angle) * dist).toFixed(1) + 'px');
leaf.style.setProperty('--leaf-rot', ((Math.random() - 0.5) * 160).toFixed(0) + 'deg');
leaf.style.setProperty('--leaf-scale', (0.55 + Math.random() * 0.6).toFixed(2));
leaf.style.setProperty('--leaf-dur', dur.toFixed(2) + 's');
leaf.style.setProperty('--flutter-dur', (0.4 + Math.random() * 0.35).toFixed(2) + 's');
leaf.appendChild(document.createElement('i'));
document.body.appendChild(leaf);
setTimeout(() => leaf.remove(), dur * 1000 + 150);
};
burstFromElement = (el) => {
if (!el) return;
const r = el.getBoundingClientRect();
if (!r.width || r.bottom < 0 || r.top > window.innerHeight) return;
// Leaf count scales with the control's width so a wide demo card
// sheds a few more than a compact icon button, capped for subtlety.
const count = Math.max(4, Math.min(9, Math.round(r.width / 26)));
for (let i = 0; i < count; i++) {
const x = r.left + 4 + Math.random() * Math.max(1, r.width - 8);
// Spawn along the upper edge, like leaves knocked off the top
const y = r.top + r.height * (0.1 + Math.random() * 0.4);
spawnLeaf(x, y);
}
};
// Listen for `click`, not `pointerdown`: a click never fires while the
// page is being scrolled, so touch users no longer trigger a shower of
// leaves every time they swipe. Leaves are also only shed by actual
// interactive controls (links/buttons and the demo widgets), so a stray
// tap on plain text or an illustration stays quiet.
let lastBurst = 0;
document.addEventListener('click', (e) => {
const control = e.target.closest('a, button, [role="button"], .btn, .mock-tab, select, .demo-progress');
if (!control) return;
const now = Date.now();
if (now - lastBurst < 180) return;
lastBurst = now;
burstFromElement(control);
}, { passive: true });
}
// Invite Detection & Bridge
const checkInvite = () => {
const isJoinPage = window.location.pathname.includes('join');
@@ -395,6 +599,7 @@ document.addEventListener('DOMContentLoaded', () => {
}
const isDE = document.documentElement.classList.contains('lang-de');
title.textContent = isDE ? 'Erfolgreich!' : 'Success!';
// eslint-disable-next-line no-unsanitized/property -- both branches are hardcoded literals, no dynamic input
desc.innerHTML = isDE
? 'Verbunden! <br><span style="color:var(--accent); font-weight:bold;">Wähle jetzt einen Video-Tab in der Erweiterung aus.</span>'
: 'Connected! <br><span style="color:var(--accent); font-weight:bold;">Now select a video tab in the extension.</span>';
@@ -412,6 +617,7 @@ document.addEventListener('DOMContentLoaded', () => {
setTimeout(updateCountdown, 1000);
const closeLabel = isDE ? 'TAB JETZT SCHLIESSEN' : 'CLOSE TAB NOW';
// eslint-disable-next-line no-unsanitized/property -- closeLabel is a hardcoded literal, no dynamic input
actions.innerHTML = `
<div class="join-card-actions">
<button class="btn btn-success" onclick="window.close()">${closeLabel}</button>
@@ -430,6 +636,7 @@ document.addEventListener('DOMContentLoaded', () => {
title.textContent = isDE ? 'Fehler' : 'Error';
desc.textContent = isDE ? `Beitritt fehlgeschlagen: ${message}` : `Join failed: ${message}`;
const retryLabel = isDE ? 'ERNEUT VERSUCHEN' : 'TRY AGAIN';
// eslint-disable-next-line no-unsanitized/property -- retryLabel is a hardcoded literal, no dynamic input
actions.innerHTML = `
<div class="join-card-actions">
<button class="btn btn-primary" onclick="location.reload()">${retryLabel}</button>
@@ -581,16 +788,16 @@ document.addEventListener('DOMContentLoaded', () => {
const midOffset = (t * -24) % 160;
const foreOffset = (t * -48) % 160;
// Bouncing ball logic (bounce Y is computed as parabolic arc)
const bouncePeriod = 0.8;
const bounceProgress = (t % bouncePeriod) / bouncePeriod;
const bounceHeight = 16;
const bounceY = 4 * bounceProgress * (1 - bounceProgress) * -bounceHeight;
// Floating lantern: slow vertical bob + softer horizontal sway on
// detuned periods, so the drift never repeats exactly in sync
const bounceY = Math.sin((t % 5.2) / 5.2 * Math.PI * 2) * 3.5;
const lanternX = Math.cos((t % 8.6) / 8.6 * Math.PI * 2) * 4;
tab.root.style.setProperty('--scroll-back', backOffset.toFixed(2) + 'px');
tab.root.style.setProperty('--scroll-mid', midOffset.toFixed(2) + 'px');
tab.root.style.setProperty('--scroll-fore', foreOffset.toFixed(2) + 'px');
tab.root.style.setProperty('--bounce-y', bounceY.toFixed(2) + 'px');
tab.root.style.setProperty('--lantern-x', lanternX.toFixed(2) + 'px');
};
const updateSyncUI = () => {
@@ -650,10 +857,7 @@ document.addEventListener('DOMContentLoaded', () => {
};
const pulse = (key) => {
const el = tabs[key].root;
el.classList.remove('sync-pulse');
void el.offsetWidth; // restart the CSS animation
el.classList.add('sync-pulse');
restartAnimation(tabs[key].root, 'sync-pulse');
};
const NAMES = { a: '🐱 ChillCat', b: '🐶 HappyDog' };
@@ -711,16 +915,15 @@ document.addEventListener('DOMContentLoaded', () => {
let seekFlashTimers = [];
const flashSeek = (root) => {
if (!root) return;
root.classList.remove('demo-seeking');
// Restart every animated layer from frame zero so the jump is visible
const film = root.querySelector('.demo-film');
if (film) {
film.classList.add('demo-reset');
void film.offsetWidth; // force reflow so the browser commits the reset
film.classList.remove('demo-reset');
requestAnimationFrame(() => {
film.classList.remove('demo-reset');
});
}
void root.offsetWidth;
root.classList.add('demo-seeking');
restartAnimation(root, 'demo-seeking');
const t = setTimeout(() => root.classList.remove('demo-seeking'), 360);
seekFlashTimers.push(t);
};
@@ -813,10 +1016,13 @@ document.addEventListener('DOMContentLoaded', () => {
inviteFly.style.left = fromPoint.x + 'px';
inviteFly.style.top = fromPoint.y + 'px';
inviteFly.style.opacity = '1';
void inviteFly.offsetWidth;
inviteFly.style.transition = '';
inviteFly.style.left = (toPoint.x - 40) + 'px';
inviteFly.style.top = (toPoint.y + 2) + 'px';
requestAnimationFrame(() => {
requestAnimationFrame(() => {
inviteFly.style.transition = '';
inviteFly.style.left = (toPoint.x - 40) + 'px';
inviteFly.style.top = (toPoint.y + 2) + 'px';
});
});
setTimeout(() => {
inviteFly.style.opacity = '0';
resolve();
@@ -829,9 +1035,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (videoSelect.options.length > 1) {
videoSelect.selectedIndex = 1;
}
videoSelect.classList.remove('demo-attn');
void videoSelect.offsetWidth;
videoSelect.classList.add('demo-attn');
restartAnimation(videoSelect, 'demo-attn');
};
if (createRoomBtn) createRoomBtn.addEventListener('click', () => setRoomJoined(true));
@@ -849,8 +1053,9 @@ document.addEventListener('DOMContentLoaded', () => {
setConnected(false);
setRoomJoined(false);
}
void scene.offsetWidth;
scene.classList.remove('demo-no-anim');
requestAnimationFrame(() => {
scene.classList.remove('demo-no-anim');
});
const showHint = () => {
if (hint) hint.classList.add('show');
@@ -895,9 +1100,10 @@ document.addEventListener('DOMContentLoaded', () => {
seekFlashTimers.forEach(clearTimeout);
seekFlashTimers = [];
// Force reflow and remove demo-no-anim:
void scene.offsetWidth;
scene.classList.remove('demo-no-anim');
// Remove demo-no-anim on next frame:
requestAnimationFrame(() => {
scene.classList.remove('demo-no-anim');
});
};
const finishDemo = () => {
if (demoFinished) return;
@@ -976,12 +1182,12 @@ document.addEventListener('DOMContentLoaded', () => {
if (userTookOver || demoRunId !== myRunId || !el) return false;
await moveTo(el, fx);
if (userTookOver || demoRunId !== myRunId) return false;
cursor.classList.remove('clicking');
void cursor.offsetWidth;
cursor.classList.add('clicking');
restartAnimation(cursor, 'clicking');
await wait(180);
if (userTookOver || demoRunId !== myRunId) return false;
if (action) action(); else el.click();
// The scripted cursor's clicks scatter leaves like real ones
burstFromElement(el);
await wait(320 + (pause || 0));
return !userTookOver && demoRunId === myRunId;
};
@@ -1163,10 +1369,12 @@ document.addEventListener('DOMContentLoaded', () => {
const isDE = document.documentElement.classList.contains('lang-de');
const originalHTML = copyBtn.innerHTML;
// eslint-disable-next-line no-unsanitized/property -- both branches are hardcoded literals, no dynamic input
copyBtn.innerHTML = isDE ? '✅ Kopiert!' : '✅ Copied!';
copyBtn.disabled = true;
setTimeout(() => {
// eslint-disable-next-line no-unsanitized/property -- restores markup captured from this same button above
copyBtn.innerHTML = originalHTML;
copyBtn.disabled = false;
}, 2000);
@@ -1478,7 +1686,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (heroBtns && heroBtns.length > 0) {
heroBtns.forEach(btn => {
const isFF = btn.classList.contains('btn-firefox');
const glowColor = isFF ? 'rgba(249, 115, 22, ' : 'rgba(99, 102, 241, ';
const glowColor = isFF ? 'rgba(201, 103, 54, ' : 'rgba(86, 174, 108, ';
btn.animate([
{ transform: 'scale(1)', boxShadow: `0 0 15px ${glowColor}0.2)` },
{ transform: 'scale(1.05)', boxShadow: `0 0 25px ${glowColor}0.5)` },
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,22 @@
{
"comment": "Generated by tools/subset-flag-font.mjs — do not edit. build.cjs fails when site flags and this manifest diverge.",
"flags": [
"BR",
"CN",
"DE",
"ES",
"FR",
"GB",
"IT",
"JP",
"KR",
"NL",
"PL",
"PT",
"RU",
"TR",
"UA"
],
"sourceFontSha256": "9f04f14429bb6a9f415c7a4dd902a918d7e81a4f7526c415496fdb063954e3b8",
"subsetSha256": "d6683cd924e343443effaa96008656e9914c168afad6cd8ac168af79e2b65811"
}
Binary file not shown.
+389 -39
View File
@@ -7,18 +7,103 @@ const path = require('path');
const crypto = require('crypto');
const sharp = require('sharp');
const esbuild = require('esbuild');
const htmlnano = require('htmlnano');
const { optimize: svgoOptimize } = require('svgo');
// CSS minifier: simple regex-based (proven, 27% reduction, no deps)
function minifyCSS(code) {
return code
.replace(/\/\*[\s\S]*?\*\//g, '')
.replace(/\s*([{}:;,])\s*/g, '$1')
// Never strip whitespace before `:`: `.parent :is(...)` is a
// descendant selector, while `.parent:is(...)` targets the parent.
.replace(/\s*([{},;])\s*/g, '$1')
.replace(/:\s+/g, ':')
.replace(/\s+/g, ' ')
.replace(/;\}/g, '}')
.trim();
}
const MIN_AVIF_KB = 0;
if (minifyCSS('.parent :is(.a, .b) { color: red; }') !== '.parent :is(.a,.b){color:red}') {
throw new Error('CSS minifier must preserve descendant combinators before functional pseudo-classes');
}
// HTML only: parser-based comment removal and conservative whitespace collapse.
// CSS, JS, JSON, and SVG keep their dedicated build steps below.
const HTML_MINIFY_OPTIONS = Object.freeze({
skipConfigLoading: true,
removeComments: 'safe',
collapseWhitespace: 'conservative'
});
const HTML_MINIFY_PRESET = Object.freeze({});
async function minifyHTML(html) {
return (await htmlnano.process(html, HTML_MINIFY_OPTIONS, HTML_MINIFY_PRESET)).html;
}
async function verifyHTMLMinifier() {
const pre = '<pre> keep\n exactly </pre>';
const jsonLd = '<script type="application/ld+json">{"name":"KoalaSync"}</script>';
const conditional = '<!--[if IE]>legacy<![endif]-->';
const result = await minifyHTML(`<!<!--nested-->--unsafe-->${pre}${jsonLd}${conditional}`);
const ordinaryComments = result.replace(conditional, '');
if (ordinaryComments.includes('<!--') || !result.includes(pre) || !result.includes(conditional)) {
throw new Error('HTML minifier security/preservation invariant failed');
}
JSON.parse(result.match(/<script type="application\/ld\+json">([\s\S]*?)<\/script>/)[1]);
}
// ── Country-flag font subset (committed artifact, validated here) ────────
// The subset itself is generated by tools/subset-flag-font.mjs (Python
// fontTools — the harfbuzz-based JS subsetters drop the COLR/CPAL color
// tables and produce invisible flags, so the build never subsets itself).
// This step verifies the committed subset still matches the site and ships
// it under a content-hashed name.
function stageFlagFontSubset(websiteDir, wwwDir) {
const { collectFlagSourceFiles, extractUsedFlags, flagToCountryCode } = require('./flag-font-utils.cjs');
const assetsDir = path.join(websiteDir, 'assets');
const subsetPath = path.join(assetsDir, 'TwemojiCountryFlags.subset.woff2');
const manifestPath = path.join(assetsDir, 'TwemojiCountryFlags.subset.json');
const regenerate = 'run "npm run subset-flags" and commit the result';
if (!fs.existsSync(subsetPath) || !fs.existsSync(manifestPath)) {
throw new Error(`Flag font subset or manifest missing ${regenerate}`);
}
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
const subset = fs.readFileSync(subsetPath);
const sha256 = buf => crypto.createHash('sha256').update(buf).digest('hex');
if (sha256(subset) !== manifest.subsetSha256) {
throw new Error(`TwemojiCountryFlags.subset.woff2 does not match its manifest ${regenerate}`);
}
const sourceFont = fs.readFileSync(path.join(assetsDir, 'TwemojiCountryFlags.woff2'));
if (sha256(sourceFont) !== manifest.sourceFontSha256) {
throw new Error(`TwemojiCountryFlags.woff2 changed since the subset was generated ${regenerate}`);
}
const usedFlags = extractUsedFlags(collectFlagSourceFiles(websiteDir));
if (usedFlags.length === 0) {
throw new Error('Flag extraction found no flag emoji extraction is broken');
}
const usedCodes = usedFlags.map(flagToCountryCode);
const missing = usedCodes.filter(c => !manifest.flags.includes(c));
if (missing.length > 0) {
throw new Error(`Flags used on the site but missing from the font subset: ${missing.join(', ')} ${regenerate}`);
}
const extra = manifest.flags.filter(c => !usedCodes.includes(c));
if (extra.length > 0) {
console.warn(` ⚠️ Subset contains unused flags (${extra.join(', ')}) "npm run subset-flags" would shrink it.`);
}
const name = `TwemojiCountryFlags.${sha8(subset)}.woff2`;
const destAssets = path.join(wwwDir, 'assets');
fs.mkdirSync(destAssets, { recursive: true });
for (const f of fs.readdirSync(destAssets)) {
if (/^TwemojiCountryFlags\.[0-9a-f]{8}\.woff2$/.test(f) && f !== name) {
fs.unlinkSync(path.join(destAssets, f));
}
}
fs.writeFileSync(path.join(destAssets, name), subset);
const pct = ((1 - subset.length / sourceFont.length) * 100).toFixed(0);
console.log(` Flag font: ${name} (${(subset.length / 1024).toFixed(1)} KB, ${usedCodes.length} flags, -${pct}% vs unsubset)`);
return name;
}
function copyDirSync(src, dest) {
fs.mkdirSync(dest, { recursive: true });
@@ -30,12 +115,13 @@ function copyDirSync(src, dest) {
}
function sha8(buf) { return crypto.createHash('sha256').update(buf).digest('hex').slice(0, 8); }
function sha384(buf) { return 'sha384-' + crypto.createHash('sha384').update(buf).digest('base64'); }
async function minifyJS(raw) {
const result = await esbuild.transform(raw, {
loader: 'js',
minify: true,
target: 'es2020'
target: 'es2022'
});
return result.code;
}
@@ -50,7 +136,12 @@ function injectAvifPictures(html) {
const srcsetMatch = attrs.match(/\bsrcset="([^"]*)"/i);
if (srcsetMatch) {
const avifSrcset = srcsetMatch[1].replace(/\.webp/gi, '.avif');
return `<picture><source srcset="${avifSrcset}" type="image/avif"><img${attrs}></picture>`;
// A <source> with width descriptors requires its own sizes
// attribute; without it browsers may pick and even reject
// candidates (observed as broken images in Chrome).
const sizesMatch = attrs.match(/\bsizes="([^"]*)"/i);
const sizesAttr = sizesMatch ? ` sizes="${sizesMatch[1]}"` : '';
return `<picture><source srcset="${avifSrcset}"${sizesAttr} type="image/avif"><img${attrs}></picture>`;
}
return `<picture><source srcset="${avifSrc}" type="image/avif"><img${attrs}></picture>`;
});
@@ -67,6 +158,7 @@ function minifyInlineSvgs(html) {
}
async function compile() {
await verifyHTMLMinifier();
console.log('Starting KoalaSync i18n compilation...');
const websiteDir = __dirname;
const wwwDir = path.join(websiteDir, 'www');
@@ -129,27 +221,82 @@ async function compile() {
console.warn(` ⚠️ Warning: ${ogSrc} not found. Skipping og-image generation.`);
}
// ── 0.7 Stage the committed flag-font subset (~45% smaller) ──
console.log('Staging flag font subset...');
const flagFontName = stageFlagFontSubset(websiteDir, wwwDir);
// ── 1. Minify CSS/JS (must happen first so hashes go into HTML) ──
console.log('Minifying CSS/JS...');
const styleRaw = fs.readFileSync(path.join(websiteDir, 'style.css'), 'utf8');
// CSS references the hashed subset instead of the raw font file
const readStyle = relativePath => fs.readFileSync(path.join(websiteDir, relativePath), 'utf8')
.replaceAll('TwemojiCountryFlags.woff2', flagFontName);
const styleModules = [
'styles/foundation.css',
'styles/hero.css',
'styles/landing-primary.css',
'styles/legal.css',
'styles/landing-controls.css',
'styles/join-spinner.css',
'styles/landing-sections.css',
'styles/join.css',
'styles/landing-faq.css',
'styles/alternatives.css',
'styles/demo.css'
];
// Keep the landing cascade equivalent to styleModules while excluding
// utility-page-only rules. A single blocking file avoids both request
// fan-out and layout shifts from activating structural CSS after paint.
const landingBundles = [
{
key: 'landing',
modules: [
'styles/foundation.css',
'styles/hero.css',
'styles/landing-primary.css',
'styles/legal.css',
'styles/landing-controls.css',
'styles/landing-sections.css',
'styles/landing-selfhost.css',
'styles/landing-faq.css',
'styles/demo.css'
]
}
];
const styleRaw = styleModules.map(readStyle).join('');
const styleMin = minifyCSS(styleRaw);
const styleHash = sha8(styleMin);
const styleName = `style.${styleHash}.min.css`;
const styleSRI = sha384(styleMin);
const compiledLandingBundles = landingBundles.map(bundle => {
const raw = bundle.modules.map(readStyle).join('');
const min = minifyCSS(raw);
return {
...bundle,
min,
name: `${bundle.key === 'landing' ? 'landing' : `landing-${bundle.key}`}.${sha8(min)}.min.css`,
sri: sha384(min)
};
});
const appRaw = fs.readFileSync(path.join(websiteDir, 'app.js'), 'utf8');
const appMin = await minifyJS(appRaw);
const appHash = sha8(appMin);
const appName = `app.${appHash}.min.js`;
const appSRI = sha384(appMin);
const langRaw = fs.readFileSync(path.join(websiteDir, 'lang-init.js'), 'utf8');
const langMin = await minifyJS(langRaw);
const langHash = sha8(langMin);
const langName = `lang-init.${langHash}.min.js`;
const langSRI = sha384(langMin);
const stylePct = ((1 - styleMin.length / styleRaw.length) * 100).toFixed(0);
const appPct = ((1 - appMin.length / appRaw.length) * 100).toFixed(0);
const langPct = ((1 - langMin.length / langRaw.length) * 100).toFixed(0);
console.log(` CSS: ${styleName} (${(styleMin.length/1024).toFixed(1)} KB, -${stylePct}%)`);
for (const bundle of compiledLandingBundles) {
console.log(` Landing ${bundle.key}: ${bundle.name} (${(bundle.min.length/1024).toFixed(1)} KB)`);
}
console.log(` App: ${appName} (${(appMin.length/1024).toFixed(1)} KB, -${appPct}%)`);
console.log(` Lang: ${langName} (${(langMin.length/1024).toFixed(1)} KB, -${langPct}%)`);
@@ -163,6 +310,9 @@ async function compile() {
// Write minified files
fs.writeFileSync(path.join(wwwDir, styleName), styleMin);
for (const bundle of compiledLandingBundles) {
fs.writeFileSync(path.join(wwwDir, bundle.name), bundle.min);
}
fs.writeFileSync(path.join(wwwDir, appName), appMin);
fs.writeFileSync(path.join(wwwDir, langName), langMin);
@@ -193,7 +343,7 @@ async function compile() {
compiled = compiled.replace(new RegExp(`\\{\\{SELECTED_${l.toUpperCase()}\\}\\}`, 'g'), l === lang ? 'selected' : '');
});
for (const [key, value] of Object.entries(locale)) {
compiled = compiled.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), value);
compiled = compiled.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), () => value);
}
return compiled;
}
@@ -202,14 +352,23 @@ async function compile() {
const telepartyTemplatePath = path.join(websiteDir, 'alternatives/teleparty.html');
const screenSharingTemplatePath = path.join(websiteDir, 'alternatives/screen-sharing.html');
const watch2getherTemplatePath = path.join(websiteDir, 'alternatives/watch2gether.html');
const scenerTemplatePath = path.join(websiteDir, 'alternatives/scener.html');
const kosmiTemplatePath = path.join(websiteDir, 'alternatives/kosmi.html');
const twosevenTemplatePath = path.join(websiteDir, 'alternatives/twoseven.html');
const overviewTemplatePath = path.join(websiteDir, 'alternatives/index.html');
const hasTelepartyTemplate = fs.existsSync(telepartyTemplatePath);
const hasScreenSharingTemplate = fs.existsSync(screenSharingTemplatePath);
const hasWatch2getherTemplate = fs.existsSync(watch2getherTemplatePath);
const hasScenerTemplate = fs.existsSync(scenerTemplatePath);
const hasKosmiTemplate = fs.existsSync(kosmiTemplatePath);
const hasTwosevenTemplate = fs.existsSync(twosevenTemplatePath);
const hasOverviewTemplate = fs.existsSync(overviewTemplatePath);
const telepartyTemplate = hasTelepartyTemplate ? fs.readFileSync(telepartyTemplatePath, 'utf8') : '';
const screenSharingTemplate = hasScreenSharingTemplate ? fs.readFileSync(screenSharingTemplatePath, 'utf8') : '';
const watch2getherTemplate = hasWatch2getherTemplate ? fs.readFileSync(watch2getherTemplatePath, 'utf8') : '';
const scenerTemplate = hasScenerTemplate ? fs.readFileSync(scenerTemplatePath, 'utf8') : '';
const kosmiTemplate = hasKosmiTemplate ? fs.readFileSync(kosmiTemplatePath, 'utf8') : '';
const twosevenTemplate = hasTwosevenTemplate ? fs.readFileSync(twosevenTemplatePath, 'utf8') : '';
const overviewTemplate = hasOverviewTemplate ? fs.readFileSync(overviewTemplatePath, 'utf8') : '';
// Preload English locale for fallback
@@ -235,7 +394,7 @@ async function compile() {
// 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);
compiled = compiled.replace(new RegExp(`\\{\\{${key}\\}\\}`, 'g'), () => value);
}
return compiled;
}
@@ -270,6 +429,24 @@ async function compile() {
const w2gCompiled = compileAlternativePage(watch2getherTemplate, locale, lang, '../', '');
fs.writeFileSync(path.join(altDir, 'watch2gether.html'), w2gCompiled);
}
if (hasScenerTemplate) {
const altDir = path.join(wwwDir, 'alternatives');
fs.mkdirSync(altDir, { recursive: true });
const scCompiled = compileAlternativePage(scenerTemplate, locale, lang, '../', '');
fs.writeFileSync(path.join(altDir, 'scener.html'), scCompiled);
}
if (hasKosmiTemplate) {
const altDir = path.join(wwwDir, 'alternatives');
fs.mkdirSync(altDir, { recursive: true });
const koCompiled = compileAlternativePage(kosmiTemplate, locale, lang, '../', '');
fs.writeFileSync(path.join(altDir, 'kosmi.html'), koCompiled);
}
if (hasTwosevenTemplate) {
const altDir = path.join(wwwDir, 'alternatives');
fs.mkdirSync(altDir, { recursive: true });
const tsCompiled = compileAlternativePage(twosevenTemplate, locale, lang, '../', '');
fs.writeFileSync(path.join(altDir, 'twoseven.html'), tsCompiled);
}
if (hasOverviewTemplate) {
const altDir = path.join(wwwDir, 'alternatives');
fs.mkdirSync(altDir, { recursive: true });
@@ -303,6 +480,24 @@ async function compile() {
const w2gCompiled = compileAlternativePage(watch2getherTemplate, locale, lang, '../../', lang + '/');
fs.writeFileSync(path.join(langAltDir, 'watch2gether.html'), w2gCompiled);
}
if (hasScenerTemplate) {
const langAltDir = path.join(langDir, 'alternatives');
fs.mkdirSync(langAltDir, { recursive: true });
const scCompiled = compileAlternativePage(scenerTemplate, locale, lang, '../../', lang + '/');
fs.writeFileSync(path.join(langAltDir, 'scener.html'), scCompiled);
}
if (hasKosmiTemplate) {
const langAltDir = path.join(langDir, 'alternatives');
fs.mkdirSync(langAltDir, { recursive: true });
const koCompiled = compileAlternativePage(kosmiTemplate, locale, lang, '../../', lang + '/');
fs.writeFileSync(path.join(langAltDir, 'kosmi.html'), koCompiled);
}
if (hasTwosevenTemplate) {
const langAltDir = path.join(langDir, 'alternatives');
fs.mkdirSync(langAltDir, { recursive: true });
const tsCompiled = compileAlternativePage(twosevenTemplate, locale, lang, '../../', lang + '/');
fs.writeFileSync(path.join(langAltDir, 'twoseven.html'), tsCompiled);
}
if (hasOverviewTemplate) {
const langAltDir = path.join(langDir, 'alternatives');
fs.mkdirSync(langAltDir, { recursive: true });
@@ -322,7 +517,8 @@ async function compile() {
{ src: 'impressum-de.html', dest: 'de/impressum.html' },
{ src: 'datenschutz-de.html', dest: 'de/datenschutz.html' },
{ src: 'impressum.html', dest: 'impressum.html' },
{ src: 'datenschutz.html', dest: 'datenschutz.html' }
{ src: 'datenschutz.html', dest: 'datenschutz.html' },
{ src: '404.html', dest: '404.html' }
];
for (const mapping of staticMappings) {
const src = path.join(websiteDir, mapping.src);
@@ -335,13 +531,16 @@ async function compile() {
}
// ── 5. Copy generic static files and verification files ──
const genericFiles = ['robots.txt', 'sitemap.xml', 'site.webmanifest', 'version.json', 'llms.txt'];
const genericFiles = ['robots.txt', 'site.webmanifest', 'version.json', 'llms.txt'];
for (const file of genericFiles) {
const src = path.join(websiteDir, file);
const dest = path.join(wwwDir, file);
if (fs.existsSync(src)) { fs.copyFileSync(src, dest); }
}
// ── 5.5 Generate dynamic sitemap ──
generateSitemap(wwwDir);
// Auto-copy Google verification files and IndexNow/txt key files from website source to www root
const websiteFiles = fs.readdirSync(websiteDir);
for (const file of websiteFiles) {
@@ -365,6 +564,11 @@ async function compile() {
const destAssets = path.join(wwwDir, 'assets');
if (fs.existsSync(srcAssets)) {
copyDirSync(srcAssets, destAssets);
// Pages use the hashed subset staged in step 0.7; ship neither the raw
// font nor the unhashed subset artifacts
fs.rmSync(path.join(destAssets, 'TwemojiCountryFlags.woff2'), { force: true });
fs.rmSync(path.join(destAssets, 'TwemojiCountryFlags.subset.woff2'), { force: true });
fs.rmSync(path.join(destAssets, 'TwemojiCountryFlags.subset.json'), { force: true });
console.log(' Assets copied.');
}
@@ -376,43 +580,80 @@ async function compile() {
console.log(' ✓ Apple touch icons copied to www root.');
}
// ── 7. Convert all WebP to AVIF (quality 70) ──
console.log('Converting WebP → AVIF...');
let avifCount = 0;
const webpFiles = fs.readdirSync(destAssets).filter(f => f.endsWith('.webp'));
for (const f of webpFiles) {
const src = path.join(destAssets, f);
const stat = fs.statSync(src);
if (stat.size < MIN_AVIF_KB * 1024) continue;
const dest = path.join(destAssets, f.replace(/\.webp$/, '.avif'));
if (fs.existsSync(dest) && fs.statSync(dest).mtimeMs >= stat.mtimeMs) continue;
await sharp(src).avif({ quality: 80, speed: 4 }).toFile(dest);
avifCount++;
}
console.log(` ${avifCount} AVIF files generated.`);
// ── 8. Post-process ALL HTML files ──
console.log('Post-processing HTML...');
function walkHtml(dir, fn) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const p = path.join(dir, entry.name);
if (entry.isDirectory()) { walkHtml(p, fn); }
else if (entry.name.endsWith('.html')) { fn(p); }
// ── 6.5 Responsive variants for the static-page mascots ──
// These pages showed 434-500px sources at 180px CSS (2x need: 360px).
// Variants feed the AVIF step below and the srcset attributes in the
// static HTML files.
console.log('Generating responsive mascot variants...');
const RESPONSIVE_VARIANTS = [
{ src: 'KoalaImprintl.webp', widths: [180, 360] },
{ src: 'KoalaPrivacy.webp', widths: [180, 360] },
{ src: 'KoalaSearching.webp', widths: [180, 360] }
];
for (const variant of RESPONSIVE_VARIANTS) {
const variantSrc = path.join(destAssets, variant.src);
if (!fs.existsSync(variantSrc)) {
throw new Error(`Responsive variant source ${variant.src} not found in assets`);
}
for (const width of variant.widths) {
const out = variantSrc.replace(/\.webp$/, `-${width}.webp`);
await sharp(variantSrc).resize({ width }).toFile(out);
}
}
walkHtml(wwwDir, (filePath) => {
// ── 7. Convert all WebP to AVIF (quality 65) ──
// Content-hash cache: mtime comparison never hit because copyDirSync
// refreshes mtimes, so every verify re-encoded all AVIFs.
console.log('Converting WebP → AVIF...');
const AVIF_OPTS = { quality: 65, speed: 4 };
const avifCachePath = path.join(websiteDir, '.avif-cache.json');
let avifCache = {};
try { avifCache = JSON.parse(fs.readFileSync(avifCachePath, 'utf8')); } catch { /* cold cache */ }
const avifCacheNext = {};
let avifCount = 0, avifCachedCount = 0;
const webpFiles = fs.readdirSync(destAssets).filter(f => f.endsWith('.webp'));
for (const f of webpFiles) {
const src = path.join(destAssets, f);
const dest = path.join(destAssets, f.replace(/\.webp$/, '.avif'));
const key = `${sha8(fs.readFileSync(src))}:q${AVIF_OPTS.quality}s${AVIF_OPTS.speed}`;
avifCacheNext[f] = key;
if (avifCache[f] === key && fs.existsSync(dest)) { avifCachedCount++; continue; }
await sharp(src).avif(AVIF_OPTS).toFile(dest);
avifCount++;
}
fs.writeFileSync(avifCachePath, JSON.stringify(avifCacheNext, null, 2) + '\n');
console.log(` ${avifCount} AVIF files generated, ${avifCachedCount} unchanged (cache).`);
// ── 8. Post-process ALL HTML files ──
console.log('Post-processing HTML...');
async function walkHtml(dir, fn) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const p = path.join(dir, entry.name);
if (entry.isDirectory()) { await walkHtml(p, fn); }
else if (entry.name.endsWith('.html')) { await fn(p); }
}
}
await walkHtml(wwwDir, async (filePath) => {
let html = fs.readFileSync(filePath, 'utf8');
// 8a. Replace hashed asset refs
html = html.replace(/href="((?:\.\.\/)*)style\.min\.css"/g, (m, prefix) => {
return `href="${prefix}${styleName}"`;
// 8a. Replace hashed asset refs and inject SRI (Subresource Integrity)
// The prefix is either any number of "../" segments or a single "/"
// (404.html must use absolute paths: it is served for arbitrary URLs).
html = html.replace(/(<link\b[^>]*?\bhref=")((?:\.\.\/)*\/?)style\.min\.css"/g, (m, before, prefix) => {
return `${before}${prefix}${styleName}" integrity="${styleSRI}" crossorigin="anonymous"`;
});
html = html.replace(/src="((?:\.\.\/)*)app\.min\.js"/g, (m, prefix) => {
return `src="${prefix}${appName}"`;
for (const bundle of compiledLandingBundles) {
const placeholder = bundle.key === 'landing' ? 'landing.min.css' : `landing-${bundle.key}.min.css`;
html = html.replace(new RegExp(`(<link\\b[^>]*?\\bhref=")((?:\\.\\.\\/)*\\/?)${placeholder.replaceAll('.', '\\.') }"`, 'g'), (m, before, prefix) => {
return `${before}${prefix}${bundle.name}" integrity="${bundle.sri}" crossorigin="anonymous"`;
});
}
html = html.replace(/(<script\b[^>]*?\bsrc=")((?:\.\.\/)*\/?)app\.min\.js"/g, (m, before, prefix) => {
return `${before}${prefix}${appName}" integrity="${appSRI}" crossorigin="anonymous"`;
});
html = html.replace(/src="((?:\.\.\/)*)lang-init\.min\.js"/g, (m, prefix) => {
return `src="${prefix}${langName}"`;
html = html.replace(/(<script\b[^>]*?\bsrc=")((?:\.\.\/)*\/?)lang-init\.min\.js"/g, (m, before, prefix) => {
return `${before}${prefix}${langName}" integrity="${langSRI}" crossorigin="anonymous"`;
});
// 8b. Inject AVIF <picture> wrappers
@@ -421,10 +662,119 @@ async function compile() {
// 8c. Minify inline SVGs
html = minifyInlineSvgs(html);
// 8d. Preload the subset flag font on pages that show flags. This
// cuts the HTML→CSS→font chain; unicode-range alone would delay the
// request until after CSS parse + layout.
if (/[\u{1F1E6}-\u{1F1FF}]{2}/u.test(html)) {
const relDir = path.relative(wwwDir, path.dirname(filePath));
// 404.html is served for arbitrary URLs and must use absolute paths
const prefix = path.basename(filePath) === '404.html'
? '/'
: (relDir ? '../'.repeat(relDir.split(path.sep).length) : '');
const preload = `<link rel="preload" as="font" type="font/woff2" href="${prefix}assets/${flagFontName}" crossorigin>`;
html = html.replace('</head>', `${preload}\n</head>`);
}
// 8e. Minify HTML (comments + indentation)
html = await minifyHTML(html);
fs.writeFileSync(filePath, html);
});
console.log('KoalaSync build finished successfully! Output: website/www/');
}
function generateSitemap(wwwDir) {
const languages = [
{ code: 'en', prefix: '', hreflang: 'en' },
{ code: 'de', prefix: 'de/', hreflang: 'de' },
{ code: 'fr', prefix: 'fr/', hreflang: 'fr' },
{ code: 'es', prefix: 'es/', hreflang: 'es' },
{ code: 'pt-BR', prefix: 'pt-BR/', hreflang: 'pt-br' },
{ code: 'ru', prefix: 'ru/', hreflang: 'ru' },
{ code: 'it', prefix: 'it/', hreflang: 'it' },
{ code: 'pl', prefix: 'pl/', hreflang: 'pl' },
{ code: 'tr', prefix: 'tr/', hreflang: 'tr' },
{ code: 'nl', prefix: 'nl/', hreflang: 'nl' },
{ code: 'ja', prefix: 'ja/', hreflang: 'ja' },
{ code: 'ko', prefix: 'ko/', hreflang: 'ko' },
{ code: 'zh', prefix: 'zh/', hreflang: 'zh' },
{ code: 'uk', prefix: 'uk/', hreflang: 'uk' },
{ code: 'pt', prefix: 'pt/', hreflang: 'pt' }
];
const today = new Date().toISOString().split('T')[0];
let xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">`;
// Static legal pages
xml += `
<url>
<loc>https://sync.koalastuff.net/imprint</loc>
<lastmod>${today}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://sync.koalastuff.net/privacy</loc>
<lastmod>${today}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://sync.koalastuff.net/de/impressum</loc>
<lastmod>${today}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://sync.koalastuff.net/de/datenschutz</loc>
<lastmod>${today}</lastmod>
<changefreq>monthly</changefreq>
<priority>0.3</priority>
</url>`;
function addPage(relativePath, changefreq, priority) {
for (const lang of languages) {
const loc = `https://sync.koalastuff.net/${lang.prefix}${relativePath}`;
xml += `
<url>
<loc>${loc}</loc>
<lastmod>${today}</lastmod>
<changefreq>${changefreq}</changefreq>
<priority>${priority}</priority>`;
for (const alt of languages) {
const altHref = `https://sync.koalastuff.net/${alt.prefix}${relativePath}`;
xml += `
<xhtml:link rel="alternate" hreflang="${alt.hreflang}" href="${altHref}"/>`;
}
const defaultHref = `https://sync.koalastuff.net/${relativePath}`;
xml += `
<xhtml:link rel="alternate" hreflang="x-default" href="${defaultHref}"/>
</url>`;
}
}
addPage('', 'weekly', '1.0');
addPage('alternatives', 'weekly', '0.7');
const subpages = [
'alternatives/teleparty',
'alternatives/screen-sharing',
'alternatives/watch2gether',
'alternatives/scener',
'alternatives/kosmi',
'alternatives/twoseven'
];
for (const sub of subpages) {
addPage(sub, 'weekly', '0.7');
}
xml += `\n</urlset>\n`;
fs.writeFileSync(path.join(wwwDir, 'sitemap.xml'), xml.trim() + '\n', 'utf8');
console.log(' ✓ Dynamically generated sitemap.xml with current date');
}
compile().catch(err => { console.error('Build failed:', err); process.exit(1); });
+86 -7
View File
@@ -25,24 +25,103 @@
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Datenschutzerklärung",
"url": "https://sync.koalastuff.net/de/datenschutz",
"description": "Datenschutzerklärung von KoalaSync - Wir nehmen Datenschutz ernst. Erfahre mehr über unseren Ansatz ohne Tracking, ohne Logs und ohne Cookies.",
"inLanguage": "de",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/de/"
}
}
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="../lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="./" class="logo-area" style="text-decoration: none;">
<img src="../assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="40" height="40">
<img src="../assets/NewLogoIcon_128.webp" alt="KoalaSync Logo" width="40" height="40">
<span>KoalaSync</span>
</a>
<div class="nav-links">
@@ -82,7 +161,7 @@
<main class="legal-content">
<div class="legal-card" data-reveal style="padding: 2rem;">
<div style="display: flex; justify-content: center;">
<img src="../assets/KoalaPrivacy.webp" alt="Niedlicher Koala, der den Datenschutz repräsentiert" class="legal-mascot" width="180" height="180">
<img src="../assets/KoalaPrivacy-180.webp" srcset="../assets/KoalaPrivacy-180.webp 180w, ../assets/KoalaPrivacy-360.webp 360w" sizes="180px" alt="Niedlicher Koala, der den Datenschutz repräsentiert" class="legal-mascot" width="180" height="180">
</div>
<h1>Datenschutz</h1>
<p style="text-align: center; text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem; border-bottom: 1px solid var(--glass-border); padding-bottom: 1.5rem; margin-bottom: 2rem;">
+48
View File
@@ -0,0 +1,48 @@
/**
* Shared helpers for the country-flag font subset.
* Used by build.cjs (validation) and tools/subset-flag-font.mjs (generation).
*
* Flags are regional-indicator pairs; tag-sequence flags (🏴 England etc.)
* are NOT extracted or subset if one is ever added it will render via the
* system emoji font.
*/
const fs = require('fs');
const path = require('path');
const FLAG_PAIR_RE = /[\u{1F1E6}-\u{1F1FF}]{2}/gu;
function collectFlagSourceFiles(websiteDir) {
const files = [];
for (const entry of fs.readdirSync(websiteDir)) {
if (entry.endsWith('.html')) files.push(path.join(websiteDir, entry));
}
for (const dir of ['alternatives', 'locales']) {
const p = path.join(websiteDir, dir);
if (!fs.existsSync(p)) continue;
for (const entry of fs.readdirSync(p)) {
if (/\.(html|json)$/.test(entry)) files.push(path.join(p, entry));
}
}
return files;
}
function extractUsedFlags(files) {
const flags = new Set();
for (const file of files) {
for (const m of fs.readFileSync(file, 'utf8').matchAll(FLAG_PAIR_RE)) {
flags.add(m[0]);
}
}
return [...flags].sort();
}
// 🇩🇪 → "DE" (for readable manifests and tool output)
function flagToCountryCode(flag) {
return [...flag].map(c => String.fromCharCode(c.codePointAt(0) - 0x1F1E6 + 65)).join('');
}
function countryCodeToFlag(code) {
return [...code].map(c => String.fromCodePoint(0x1F1E6 + c.charCodeAt(0) - 65)).join('');
}
module.exports = { FLAG_PAIR_RE, collectFlagSourceFiles, extractUsedFlags, flagToCountryCode, countryCodeToFlag };
+91 -12
View File
@@ -25,24 +25,103 @@
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Impressum",
"url": "https://sync.koalastuff.net/de/impressum",
"description": "Impressum (Legal Notice) von KoalaSync - Anbieterkennzeichnung und Kontaktinformationen für die Open-Source Video-Synchronisations-Erweiterung.",
"inLanguage": "de",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/de/"
}
}
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="../lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="./" class="logo-area" style="text-decoration: none;">
<img src="../assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="40" height="40">
<img src="../assets/NewLogoIcon_128.webp" alt="KoalaSync Logo" width="40" height="40">
<span>KoalaSync</span>
</a>
<div class="nav-links">
@@ -82,7 +161,7 @@
<main class="legal-content">
<div class="legal-card" data-reveal style="padding: 2rem;">
<div style="display: flex; justify-content: center;">
<img src="../assets/KoalaImprintl.webp" alt="Niedlicher Koala, der das Impressum repräsentiert" class="legal-mascot" width="180" height="180">
<img src="../assets/KoalaImprintl-180.webp" srcset="../assets/KoalaImprintl-180.webp 180w, ../assets/KoalaImprintl-360.webp 360w" sizes="180px" alt="Niedlicher Koala, der das Impressum repräsentiert" class="legal-mascot" width="180" height="180">
</div>
<h1>Impressum / Anbieterinformationen</h1>
<p style="text-align: center; text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem; border-bottom: 1px solid var(--glass-border); padding-bottom: 1.5rem; margin-bottom: 2rem;">
@@ -96,12 +175,12 @@
E-Mail: <span class="email-reveal" data-user="koalasync" data-domain="koalastuff.net" style="color: var(--accent); cursor: pointer; text-decoration: underline;">[E-Mail anzeigen]</span>
</p>
<p style="margin-top: 0.75rem;">
<span style="opacity: 0.6;">🔒 Private Nachricht:</span>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" style="color: var(--accent); text-decoration: none;">@koalastuff auf Mastodon</a>
<span class="legal-inline-label">🔒 Private Nachricht:</span>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" class="legal-inline-link">@koalastuff auf Mastodon</a>
</p>
<p style="margin-top: 0.5rem;">
<span style="opacity: 0.6;">🐛 Fehlerberichte und Sicherheitsmeldungen:</span>
<a href="https://github.com/Shik3i/KoalaSync/issues" target="_blank" rel="noopener" style="color: var(--accent); text-decoration: none;">GitHub Issues</a>
<span class="legal-inline-label">🐛 Fehlerberichte und Sicherheitsmeldungen:</span>
<a href="https://github.com/Shik3i/KoalaSync/issues" target="_blank" rel="noopener" class="legal-inline-link">GitHub Issues</a>
</p>
</section>
@@ -111,7 +190,7 @@
KoalaSync ist eine kostenlose und quelloffene Browser-Erweiterung. Der Quellcode ist auf GitHub unter der MIT-Lizenz verfügbar.
</p>
<p style="margin-top: 0.5rem;">
Informationen zum Datenschutz, einschließlich Hosting, Access Logs, Relay-Verhalten und Betroffenenrechten, finden Sie in der <a href="datenschutz" style="color: var(--accent); text-decoration: none;">Datenschutzerklärung</a>.
Informationen zum Datenschutz, einschließlich Hosting, Access Logs, Relay-Verhalten und Betroffenenrechten, finden Sie in der <a href="datenschutz" class="legal-inline-link">Datenschutzerklärung</a>.
</p>
</section>
+91 -12
View File
@@ -25,24 +25,103 @@
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Legal Notice",
"url": "https://sync.koalastuff.net/imprint",
"description": "Legal Notice (Impressum) of KoalaSync - Contact information and operator details for the open-source video synchronization extension.",
"inLanguage": "en",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/"
}
}
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="./" class="logo-area" style="text-decoration: none;">
<img src="assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="40" height="40">
<img src="assets/NewLogoIcon_128.webp" alt="KoalaSync Logo" width="40" height="40">
<span>KoalaSync</span>
</a>
<div class="nav-links">
@@ -82,7 +161,7 @@
<main class="legal-content">
<div class="legal-card" data-reveal style="padding: 2rem;">
<div style="display: flex; justify-content: center;">
<img src="assets/KoalaImprintl.webp" alt="Cute Koala representing the legal notice page" class="legal-mascot" width="180" height="180">
<img src="assets/KoalaImprintl-180.webp" srcset="assets/KoalaImprintl-180.webp 180w, assets/KoalaImprintl-360.webp 360w" sizes="180px" alt="Cute Koala representing the legal notice page" class="legal-mascot" width="180" height="180">
</div>
<h1>Legal Notice</h1>
<p style="text-align: center; text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem; border-bottom: 1px solid var(--glass-border); padding-bottom: 1.5rem; margin-bottom: 2rem;">
@@ -96,12 +175,12 @@
E-Mail: <span class="email-reveal" data-user="koalasync" data-domain="koalastuff.net" style="color: var(--accent); cursor: pointer; text-decoration: underline;">[Show Email]</span>
</p>
<p style="margin-top: 0.75rem;">
<span style="opacity: 0.6;">🔒 Private message:</span>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" style="color: var(--accent); text-decoration: none;">@koalastuff on Mastodon</a>
<span class="legal-inline-label">🔒 Private message:</span>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" class="legal-inline-link">@koalastuff on Mastodon</a>
</p>
<p style="margin-top: 0.5rem;">
<span style="opacity: 0.6;">🐛 Bug reports and security concerns:</span>
<a href="https://github.com/Shik3i/KoalaSync/issues" target="_blank" rel="noopener" style="color: var(--accent); text-decoration: none;">GitHub Issues</a>
<span class="legal-inline-label">🐛 Bug reports and security concerns:</span>
<a href="https://github.com/Shik3i/KoalaSync/issues" target="_blank" rel="noopener" class="legal-inline-link">GitHub Issues</a>
</p>
</section>
@@ -111,7 +190,7 @@
KoalaSync is a free and open-source browser extension. The source code is available on GitHub under the MIT License.
</p>
<p style="margin-top: 0.5rem;">
For privacy-related information, including hosting, access logs, relay behavior, and data subject rights, please see the <a href="privacy" style="color: var(--accent); text-decoration: none;">Privacy Policy</a>.
For privacy-related information, including hosting, access logs, relay behavior, and data subject rights, please see the <a href="privacy" class="legal-inline-link">Privacy Policy</a>.
</p>
</section>
+88 -15
View File
@@ -27,26 +27,89 @@
<meta name="twitter:image" content="https://sync.koalastuff.net/assets/og-image.png">
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="./" class="logo-area" style="text-decoration: none;">
<img src="assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="64" height="64">
<img src="assets/NewLogoIcon_128.webp" alt="KoalaSync Logo" width="64" height="64">
<span>KoalaSync</span>
</a>
<div class="nav-links">
<div class="nav-links" id="primary-nav" role="navigation" aria-label="Primary">
<a href="./" style="display: inline-flex; align-items: center; gap: 6px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="width: 16px; height: 16px; display: block;"><path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
<span lang="de">Startseite</span><span lang="en">Home</span>
@@ -57,6 +120,10 @@
</a>
</div>
<div class="nav-right">
<button class="theme-toggle" id="theme-toggle" type="button" aria-label="Toggle light/dark mode" title="Toggle light/dark mode">
<svg class="theme-icon-sun" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></svg>
<svg class="theme-icon-moon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18" aria-hidden="true"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>
</button>
<div class="lang-select-container">
<select class="lang-dropdown" aria-label="Select Language">
<option value="en">🇬🇧 English</option>
@@ -75,7 +142,7 @@
</select>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="chevron-icon"><polyline points="6 9 12 15 18 9"/></svg>
</div>
<button class="hamburger" aria-label="Menu" aria-expanded="false"></button>
<button class="hamburger" aria-label="Menu" aria-expanded="false" aria-controls="primary-nav"></button>
</div>
</div>
</nav>
@@ -88,8 +155,8 @@
<div class="join-status-visual">
<div class="status-ring active-pulse" id="status-ring"></div>
<div id="join-status-icon" style="z-index: 2; transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); display: flex; align-items: center; justify-content: center;">
<img src="assets/KoalaSearching.webp" alt="A cute koala looking through a telescope searching for your extension" class="join-status-mascot searching-mascot join-status-pulse" lang="en">
<img src="assets/KoalaSearching.webp" alt="Ein niedlicher Koala schaut durch ein Fernrohr und sucht nach deiner Erweiterung" class="join-status-mascot searching-mascot join-status-pulse" lang="de">
<img src="assets/KoalaSearching-180.webp" srcset="assets/KoalaSearching-180.webp 180w, assets/KoalaSearching-360.webp 360w" sizes="175px" alt="A cute koala looking through a telescope searching for your extension" class="join-status-mascot searching-mascot join-status-pulse" lang="en">
<img src="assets/KoalaSearching-180.webp" srcset="assets/KoalaSearching-180.webp 180w, assets/KoalaSearching-360.webp 360w" sizes="175px" alt="Ein niedlicher Koala schaut durch ein Fernrohr und sucht nach deiner Erweiterung" class="join-status-mascot searching-mascot join-status-pulse" lang="de">
</div>
</div>
@@ -115,13 +182,19 @@
<footer>
<div class="container">
<p>&copy; 2026 KoalaSync. Open source under the MIT License.</p>
<p lang="en" style="font-size: 0.8rem; margin-top: 0.5rem;">No relay logs. No tracking. Website access logs are deleted after 7 days.</p>
<p lang="de" style="font-size: 0.8rem; margin-top: 0.5rem;">Keine Relay-Logs. Kein Tracking. Website-Access-Logs werden nach 7 Tagen gelöscht.</p>
<p>&copy; 2026 KoalaSync. <span lang="en">Open source under the MIT License.</span><span lang="de">Open Source unter der MIT-Lizenz.</span></p>
<p style="font-size: 0.8rem; margin-top: 0.5rem;"><span lang="en">No relay logs. No tracking. Website access logs are deleted after 7 days.</span><span lang="de">Keine Relay-Logs. Kein Tracking. Website-Access-Logs werden nach 7 Tagen gelöscht.</span></p>
<p class="footer-disclaimer" style="margin-top: 1.2rem;"><span lang="en">KoalaSync is not affiliated with, endorsed by, or associated with Netflix, Disney+, Amazon, YouTube, Twitch, or any other streaming platform. All trademarks are property of their respective owners.</span><span lang="de">KoalaSync ist nicht mit Netflix, Disney+, Amazon, YouTube, Twitch oder anderen Streaming-Plattformen verbunden, wird von diesen nicht unterstützt oder steht in keiner Beziehung zu diesen. Alle Markenrechte liegen bei ihren jeweiligen Inhabern.</span></p>
<div style="margin-top: 1.5rem; font-size: 0.8rem; display: flex; justify-content: center; align-items: center; gap: 1.5rem; flex-wrap: wrap;">
<a href="impressum" style="color: var(--text-muted); text-decoration: none;"><span lang="en">Legal Notice</span><span lang="de">Impressum</span></a>
<a href="datenschutz" style="color: var(--text-muted); text-decoration: none;"><span lang="en">Privacy Policy</span><span lang="de">Datenschutz</span></a>
<a href="imprint" lang="en" style="color: var(--text-muted); text-decoration: none;">Legal Notice</a>
<a href="de/impressum" lang="de" style="color: var(--text-muted); text-decoration: none;">Impressum</a>
<a href="privacy" lang="en" style="color: var(--text-muted); text-decoration: none;">Privacy Policy</a>
<a href="de/datenschutz" lang="de" style="color: var(--text-muted); text-decoration: none;">Datenschutz</a>
<a href="alternatives"><span lang="en">Guides & comparisons</span><span lang="de">Vergleiche & Anleitungen</span></a>
<a href="https://support.koalastuff.net" target="_blank" rel="noopener" title="Support KoalaSync" style="color: #fff; text-decoration: none; display: inline-flex; align-items: center; gap: 6px; background: #b94642; border: 1px solid rgba(255,255,255,0.18); border-radius: 999px; padding: 3px 9px; font-size: 0.72rem; font-weight: 700; line-height: 1;">
<span aria-hidden="true"></span>
<span>Support KoalaSync</span>
</a>
<a href="https://mastodon.social/@koalastuff" rel="me noopener" target="_blank" style="color: var(--text-muted); text-decoration: none; display: inline-flex; align-items: center; gap: 4px;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="14" height="14" aria-hidden="true" style="display: block;"><path d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z"/></svg>
Mastodon
+12 -9
View File
@@ -10,17 +10,22 @@
}
};
var safeSetLocalStorage = function(key, val) {
var getSystemTheme = function() {
try {
localStorage.setItem(key, val);
return window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
} catch (_) {
return;
return 'dark';
}
};
// Apply saved theme before first paint (dark is the default, no class needed)
if (safeGetLocalStorage('koala_theme') === 'light') {
// Apply the effective theme before first paint. A saved preference wins;
// otherwise first-time visitors follow their browser/system setting.
var savedTheme = safeGetLocalStorage('koala_theme');
var effectiveTheme = savedTheme === 'light' || savedTheme === 'dark' ? savedTheme : getSystemTheme();
if (effectiveTheme === 'light') {
html.classList.add('theme-light');
} else {
html.classList.remove('theme-light');
}
// Mapping of browser language codes to KoalaSync locale directories
@@ -77,10 +82,8 @@
}
if (hasStaticLang) {
var isLegal = path.indexOf('impressum') !== -1 || path.indexOf('datenschutz') !== -1 || path.indexOf('imprint') !== -1 || path.indexOf('privacy') !== -1;
if (!isLegal) {
safeSetLocalStorage('koala_lang', activeLang);
}
// Do not persist a static page language merely because the visitor landed
// there. The explicit dropdown handler in app.js owns language preference.
} else {
var savedLang = safeGetLocalStorage('koala_lang');
var browserLang = getBrowserLang();
+106 -22
View File
@@ -1,33 +1,117 @@
# KoalaSync
> Watch Netflix, YouTube, Twitch & any HTML5 video in perfect sync with friends. Free, open-source browser extension for Chrome and Firefox. No sign-up needed.
> KoalaSync is a free, open-source browser extension that keeps video playback synchronized between friends. It works with Netflix, YouTube, Twitch, Emby, Jellyfin and most websites that expose an HTML5 video player. No account is required.
KoalaSync is a privacy-first peer-to-peer video synchronization tool. It uses WebRTC for direct connections between peers — no video data ever passes through a server. The relay server is only used for signaling and optional room-based coordination. Self-hostable, MIT licensed.
KoalaSync synchronizes playback controls; it does not stream, proxy, host, download or unlock video. Every participant watches the content locally in their own browser and must have legitimate access to the selected website or streaming service.
## Features
## Quick fit assessment
- [Sync any HTML5 video](https://sync.koalastuff.net/): Works with Netflix, Emby, Jellyfin, YouTube, Twitch, Amazon Prime Video, Disney+, Crunchyroll, HBO Max and more
- [Host & co-host controls](https://sync.koalastuff.net/#features): Synchronized play, pause, seek, host control mode, co-host roles
- [Privacy-first](https://sync.koalastuff.net/#features): No accounts, no tracking, no data collection, peer-to-peer by design
- [Available in 15 languages](https://sync.koalastuff.net/): English, Deutsch, Français, Español, Português, Italiano, Nederlands, Polski, Türkçe, Русский, 日本語, 한국어, 中文, Українська
KoalaSync is a good fit when users:
## Download
- want synchronized play, pause and seeking while watching remotely
- already use a separate voice or video chat application
- want to keep the streaming site's native video and audio quality
- need support beyond a single streaming platform
- prefer a free, ad-free and open-source tool without user accounts
- want the option to self-host the synchronization relay
- [Chrome Web Store](https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc): Install KoalaSync for Chrome, Edge, and other Chromium-based browsers
- [Firefox Add-ons](https://addons.mozilla.org/de/firefox/addon/koalasync/): Install KoalaSync for Firefox
- [GitHub Releases](https://github.com/Shik3i/KoalaSync/releases): Manual download and release notes
KoalaSync is not a fit when users need:
## Technical
- video or screen sharing to people who do not have access to the content
- a hosted video library, remote browser or cloud-streaming service
- built-in text, voice or webcam chat
- a mobile app or Safari extension
- guaranteed compatibility with a player that does not expose an accessible HTML5 video element
- [Source code](https://github.com/Shik3i/KoalaSync): Full MIT-licensed source on GitHub (extension, server, website)
- [Changelog](https://github.com/Shik3i/KoalaSync/blob/main/docs/CHANGELOG.md): Version history and release notes
- [Self-hosting guide](https://sync.koalastuff.net/#self-hosting): Run your own relay server
- [Server](https://sync.koalastuff.net/): Node.js WebSocket relay, port 54000
## How it works
## Optional
1. Each participant installs KoalaSync for Chrome, Firefox or a compatible desktop browser.
2. One participant creates a room and shares the generated invitation link.
3. Each participant opens the video locally and selects its browser tab in KoalaSync.
4. The extensions exchange room and playback events through a lightweight WebSocket relay.
5. Each extension applies play, pause and seek actions to the selected local video element.
- [Alternatives hub](https://sync.koalastuff.net/alternatives/): Comparison with Teleparty, Scener, other sync tools
- [Privacy policy](https://sync.koalastuff.net/privacy.html): Data handling and privacy information
- [Imprint](https://sync.koalastuff.net/imprint.html): Legal notice
- [Sitemap](https://sync.koalastuff.net/sitemap.xml): Full site index
- [Join a room](https://sync.koalastuff.net/join.html): Direct room join page
The relay forwards synchronization messages between room participants. It never receives or forwards the video or audio stream itself. The official public relay is reached through `wss://syncserver.koalastuff.net`; self-hosted deployments commonly run the Node.js service internally on port 3000 behind a TLS reverse proxy.
## Main features
- Synchronized play, pause and seeking
- Host-only control mode and assignable co-host roles
- Episode auto-sync with a lobby that waits until participants are ready
- Video-title matching to help users select corresponding tabs
- Optional manual force-sync controls
- Local audio compressor for balancing quiet dialogue and loud scenes
- Invitation links that can configure official or custom relay servers
- Interface translations in 15 languages
- Self-hostable Node.js WebSocket relay
## Privacy and security
- No KoalaSync account or registration
- No advertising, analytics, tracking pixels or third-party telemetry
- No persistent room database; active room and peer state exists in relay memory only
- Room state is removed when participants leave and inactive rooms expire
- The official relay processes synchronization state, peer identifiers, usernames and optional media metadata while a room is active
- IP addresses are processed temporarily for connection limits and abuse protection
- Official relay console events are ephemeral and are not archived as persistent user logs
- Invitation credentials are placed in the URL fragment, which is not sent to the website server
- The extension activates its video-control logic only in the tab selected by the user
- Source code for the extension, relay and website is publicly auditable under the MIT License
For exact retention periods, metadata controls and permission details, read the [privacy policy](https://sync.koalastuff.net/privacy) and [technical privacy documentation](https://github.com/Shik3i/KoalaSync/blob/main/docs/PRIVACY.md).
## Supported environments
- Google Chrome
- Mozilla Firefox
- Microsoft Edge and other Chromium-based desktop browsers
- Windows, macOS, Linux and ChromeOS
- Websites with an accessible HTML5 `<video>` element
Compatibility depends on each website's player implementation and can change when a streaming provider updates its site. See the [tested-services matrix](https://github.com/Shik3i/KoalaSync/blob/main/docs/TESTED_SERVICES.md) for current details and limitations.
## Install KoalaSync
- [Chrome Web Store](https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc): Chrome, Edge and compatible Chromium browsers
- [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/koalasync/): Firefox
- [GitHub Releases](https://github.com/Shik3i/KoalaSync/releases): Release notes and manual packages
## Technical information
- Current website release: 2.5.4
- License: MIT
- Extension runtime: dependency-free browser extension code
- Relay: Node.js with Socket.IO-compatible WebSocket messaging
- Persistence: RAM-only room state; no room database
- Official relay: `wss://syncserver.koalastuff.net`
- Self-hosting: Docker image `ghcr.io/shik3i/koalasync:latest`
- Source repository: [github.com/Shik3i/KoalaSync](https://github.com/Shik3i/KoalaSync)
## Documentation
- [How KoalaSync works](https://github.com/Shik3i/KoalaSync/blob/main/docs/HOW_IT_WORKS.md)
- [Architecture](https://github.com/Shik3i/KoalaSync/blob/main/docs/ARCHITECTURE.md)
- [WebSocket protocol](https://github.com/Shik3i/KoalaSync/blob/main/docs/PROTOCOL.md)
- [Privacy](https://github.com/Shik3i/KoalaSync/blob/main/docs/PRIVACY.md)
- [Security policy](https://github.com/Shik3i/KoalaSync/blob/main/SECURITY.md)
- [Self-hosting guide](https://sync.koalastuff.net/#self-hosting)
- [Changelog](https://github.com/Shik3i/KoalaSync/blob/main/docs/CHANGELOG.md)
## Comparisons and alternatives
- [Watch-party comparison overview](https://sync.koalastuff.net/alternatives/)
- [KoalaSync vs Teleparty](https://sync.koalastuff.net/alternatives/teleparty)
- [KoalaSync vs Watch2Gether](https://sync.koalastuff.net/alternatives/watch2gether)
- [KoalaSync vs Scener](https://sync.koalastuff.net/alternatives/scener)
- [KoalaSync vs Kosmi](https://sync.koalastuff.net/alternatives/kosmi)
- [KoalaSync vs TwoSeven](https://sync.koalastuff.net/alternatives/twoseven)
- [KoalaSync vs screen sharing](https://sync.koalastuff.net/alternatives/screen-sharing)
## Contact and project status
- [Main website](https://sync.koalastuff.net/)
- [GitHub issues](https://github.com/Shik3i/KoalaSync/issues): Bugs, compatibility reports and feature requests
- [Mastodon](https://mastodon.social/@koalastuff): Private contact and project updates
- [Legal notice](https://sync.koalastuff.net/imprint)
KoalaSync is an independent project and is not affiliated with, endorsed by or associated with Netflix, Disney+, Amazon, YouTube, Twitch or any other streaming platform. All trademarks belong to their respective owners.
+40 -1
View File
@@ -24,7 +24,7 @@
"DEMO_JOINED": "Raum beigetreten",
"DEMO_TAB_SELECTED": "Tab ausgewählt",
"DEMO_SELECT_PLACEHOLDER": "Video-Tab wählen…",
"MOBILE_DEMO_CTA": "So funktioniert's ansehen",
"MOBILE_DEMO_CTA": "Live-Demo ansehen",
"MOBILE_DEMO_TITLE": "KoalaSync Live-Demo",
"MOBILE_DEMO_CLOSE": "Demo schließen",
"ADD_TO_CHROME": "Zu Chrome hinzufügen",
@@ -235,6 +235,45 @@
"ALT_W2G_LIMITS_BODY": "KoalaSync hat <strong>keine eigene Playlist oder Suche</strong> wie Watch2Gether. Auf YouTube führt das dazu, dass das automatische Abspielen der nächsten Videos nicht synchron läuft.<br><br>Zudem gibt es <strong>keinen integrierten Chat</strong> und KoalaSync läuft aktuell nur auf Desktop-Browsern. Es ist so gedacht, dass ihr ohnehin über Discord, Teamspeak oder andere Voice-Tools miteinander sprecht.",
"ALT_W2G_SUMMARY_TITLE": "Kurz gesagt",
"ALT_W2G_SUMMARY_BODY": "Für spontane YouTube-Sessions mit Playlists und integriertem Chat ist Watch2Gether die beste Wahl. Für echte Premium-Streaming-Plattformen (wie Netflix, Prime Video, Disney+), selbstgehostete Server (Jellyfin, Plex, Emby) und maximale Flexibilität im Browser ist KoalaSync das passendere und schlankere Tool.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: Welche Watch-Party-Lösung passt besser?",
"ALT_SCENER_META_DESC": "Ein ehrlicher Vergleich von KoalaSync und Scener. Erfahre, wann Scener mit Webcam-Chat punktet und warum KoalaSync für werbefreie Filmabende die Nase vorn hat.",
"ALT_SCENER_INTRO": "KoalaSync und Scener gehen das Thema Watch-Partys aus zwei völlig verschiedenen Richtungen an. Scener versteht sich als virtuelles Kino mit integriertem Video-Chat und interaktiven Räumen. KoalaSync ist dagegen eine minimalistische, datenschutzfreundliche Browser-Erweiterung, die einfach nur deine Videowiedergabe synchronisiert. Welches Tool besser zu dir passt, hängt vor allem davon ab, wie wichtig dir Webcams und integrierter Chat beim Streamen sind.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Wann Scener die bessere Wahl ist",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener ist eine solide Wahl, wenn du eine <strong>All-in-One-Social-Plattform</strong> mit integriertem Video- und Audio-Chat direkt im Browserfenster suchst. Scener erstellt einen virtuellen Raum, in dem der Player und die Webcams deiner Freunde nebeneinander angezeigt werden. Dies ist ideal für große, öffentliche Watch-Partys oder virtuelle Streaming-Events, bei denen der soziale Aspekt im Vordergrund steht. Beachte jedoch, dass die kostenlose Basisversion durch Werbung finanziert wird und Scener viele Funktionen (wie werbefreies Schauen und unbegrenzten Video-Chat) hinter einem kostenpflichtigen Premium-Abo ($5.79/Monat oder $39.99/Jahr) versteckt.",
"ALT_SCENER_WHEN_KOALA_TITLE": "Wann KoalaSync besser passt",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync punktet bei <strong>Bildqualität, Datenschutz und Einfachheit</strong>:<br><br>• <strong>Keine Accounts</strong>: Du musst dich nicht registrieren, einloggen oder Profile verwalten. Einfach Extension aktivieren, Raumcode teilen und losschauen.<br>• <strong>Echte native Qualität (4K/HDR)</strong>: Scener streamt ein komprimiertes Bild von einem virtuellen Cloud-Server, was zu Qualitätsverlusten und Rucklern führen kann. KoalaSync synchronisiert den echten Original-Player direkt auf deinem Computer. Du schaust Filme also in voller nativer Auflösung deines Streaming-Abos.<br>• <strong>Geringer Datenverbrauch</strong>: Da nur Steuerungsdaten (Play, Pause, Zeitstempel) übertragen werden, verbraucht KoalaSync fast keine zusätzliche Bandbreite. Scener streamt das gesamte Video und Kamerabilder über Cloud-Server, was leistungsschwächere Laptops und Internetleitungen stark beanspruchen kann.<br>• <strong>100 % kostenlos & werbefrei</strong>: Keine monatlichen Gebühren, keine Werbung.<br>• <strong>Lokale Videodateien</strong>: Da KoalaSync lokal läuft, kannst du sogar eigene Videodateien (z. B. MP4) synchron mit Freunden schauen. Ziehe die Datei einfach per Drag-and-Drop in ein Browser-Tab Scener kann das bauartbedingt (da Scener in der Cloud läuft) nicht.",
"ALT_SCENER_MAIN_DIFF_TITLE": "Der wichtigste Unterschied",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener ist ein <strong>kommerzielles soziales Netzwerk</strong> für Watch-Partys, das auf virtuellen Cloud-Browsern basiert und mit Werbung sowie monatlichen Abonnements finanziert wird. KoalaSync ist eine <strong>datenschutzfreundliche, kostenlose Synchronisations-Erweiterung</strong>, die sich direkt in deine Browser-Tabs einklinkt. Sie überlässt den Chat Programmen wie Discord oder Teamspeak und konzentriert sich ganz darauf, deine Wiedergabe flüssig, privat und in bester Originalqualität zu synchronisieren.",
"ALT_SCENER_LIMITS_TITLE": "Ehrliche Grenzen",
"ALT_SCENER_LIMITS_BODY": "KoalaSync bietet <strong>keinen eigenen Chat und keine Webcam-Unterstützung</strong>. Es ist ausschließlich als Sync-Tool gedacht und erfordert ein separates Kommunikations-Tool deiner Wahl. Zudem ist KoalaSync derzeit nur für Desktop-Browser verfügbar. Die Kompatibilität lokaler Videodateien hängt außerdem davon ab, ob dein Browser das jeweilige Videoformat und die Audio-Codecs nativ abspielen kann.",
"ALT_SCENER_SUMMARY_TITLE": "Kurz gesagt",
"ALT_SCENER_SUMMARY_BODY": "Für große Watch-Partys mit Webcam-Chat und Social-Features im selben Fenster ist Scener die richtige Wahl, sofern dich Werbung und Premium-Gating nicht stören. Wenn du einfach nur komplett kostenlos, werbefrei und ungestört im echten Player (inklusive Netflix, Prime Video, Disney+ oder sogar lokalen Dateien im Browser) synchron schauen willst und ohnehin in Discord telefonierst, ist KoalaSync die sauberere und performantere Lösung.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: Welche Netflix-Party-Alternative passt besser?",
"ALT_KOSMI_META_DESC": "Ein ehrlicher Vergleich von KoalaSync und Kosmi. Erfahre, warum Kosmis bequeme No-Extension-Lösung punktet und wann KoalaSyncs native Bildqualität gewinnt.",
"ALT_KOSMI_INTRO": "Sowohl KoalaSync als auch Kosmi bieten hervorragende Möglichkeiten, um Netflix, YouTube und andere Plattformen synchron mit Freunden zu schauen. Doch technisch arbeiten beide Tools grundlegend verschieden. Kosmi setzt auf virtuelle Cloud-Browser, die ohne Erweiterung direkt im Web laufen. KoalaSync ist eine minimalistische Browser-Erweiterung, die deinen lokalen Player synchronisiert. Welcher Ansatz für dich der bessere ist, hängt von deinen Ansprüchen an Bildqualität, Komfort und Datenschutz ab.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Wann Kosmi die bessere Wahl ist",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi ist unschlagbar, wenn du <strong>überhaupt nichts installieren</strong> möchtest oder auf Geräten wie Tablets oder Smartphones mitschauen willst. Da Kosmi über virtuelle Browser in der Cloud läuft, reicht ein einfacher Weblink aus, um beizutreten. Zudem bietet Kosmi eine All-in-One-Plattform: Neben Video-Streaming könnt ihr in den virtuellen Räumen auch Multiplayer-Spiele spielen (z. B. NES/SNES-Klassiker oder Pokertische) und den integrierten Webcam-, Voice- und Text-Chat nutzen. Wenn der Fokus auf einem geselligen Spiele- und Videoabend ohne jegliche Installation liegt, ist Kosmi eine fantastische Lösung.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Wann KoalaSync besser passt",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync glänzt durch seine <strong>native Wiedergabe, maximale Sicherheit und Performance</strong>:<br><br>• <strong>Keine Sicherheitsrisiken</strong>: Bei Kosmi musst du dich auf einem fremden virtuellen Computer in der Cloud in deinen Netflix- oder Prime-Account einloggen. Bei KoalaSync loggst du dich wie gewohnt auf der echten Streaming-Website in deinem eigenen Browser ein. Deine Passwörter verlassen niemals deinen Computer.<br>• <strong>Volle Bildqualität (4K/HDR)</strong>: Kosmi streamt das Bild des virtuellen Browsers als komprimierten Videofeed an dich. KoalaSync synchronisiert die Player lokal: Du genießt Filme in der vollen, gestochen scharfen Originalqualität deines Abos, ohne Pixelmatsch oder Ruckler.<br>• <strong>Schonend für Internet und Akku</strong>: Da KoalaSync nur Steuerdaten (Play/Pause/Zeitstempel) sendet, verbraucht es fast null Bandbreite. Kosmi streamt permanent ein HD-Video aus der Cloud, was schwache Internetverbindungen überlasten kann.<br>• <strong>Lokale Videodateien</strong>: Wenn du ein eigenes Video synchron schauen willst, ziehst du die MP4-Datei einfach per Drag-and-Drop in ein Browser-Tab. KoalaSync synchronisiert sie sofort. Kosmi kann auf deine lokalen Dateien auf der Festplatte nicht zugreifen.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "Der wichtigste Unterschied",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi ist ein <strong>virtueller Treffpunkt</strong> in der Cloud, der einen Remote-Browser per Video-Feed streamt, damit niemand eine Erweiterung installieren muss. KoalaSync ist eine <strong>Schnittstelle für den eigenen Browser</strong>, die sich direkt in den nativen Player auf der echten Website einklinkt. Während Kosmi vielseitiger für Minispiele und Geräte-Kompatibilität ist, bietet KoalaSync das sicherere, flüssigere und schärfere Streaming-Erlebnis im Original-Player.",
"ALT_KOSMI_LIMITS_TITLE": "Ehrliche Grenzen",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync erfordert die <strong>Installation einer Browser-Erweiterung</strong> und läuft derzeit nur auf Desktop-PCs (Windows, Mac, Linux). Es hat <strong>keine integrierten Chats oder Webcams</strong>, da es so gedacht ist, dass ihr ohnehin über Discord oder andere Voice-Tools miteinander sprecht. Zudem bietet KoalaSync keine integrierten Spiele wie Kosmi.",
"ALT_KOSMI_SUMMARY_TITLE": "Kurz gesagt",
"ALT_KOSMI_SUMMARY_BODY": "Für gemütliche Spieleabende inklusive SNES-Klassikern und einfachem Beitreten ohne jegliche Installation auf Smartphones oder Tablets ist Kosmi ideal. Für private Filmabende auf Netflix, Prime Video, Disney+ oder Plex in bester 4K-Originalqualität, mit maximaler Passwort-Sicherheit und minimaler Internet-Belastung ist KoalaSync die deutlich überlegene Wahl.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: Welche Watch-Party-Lösung passt besser?",
"ALT_TWOSEVEN_META_DESC": "Ein ehrlicher Vergleich von KoalaSync und TwoSeven. Erfahre, wann TwoSeven mit integrierter Webcam punktet und warum KoalaSync für Disney+ und Netflix die Nase vorn hat.",
"ALT_TWOSEVEN_INTRO": "Sowohl KoalaSync als auch TwoSeven nutzen denselben grundlegenden Ansatz für Watch-Partys: Sie synchronisieren den originalen Videoplayer direkt in deinem Browser, anstatt ein komprimiertes Bild aus der Cloud zu streamen. Dadurch bleibt die Bildqualität bei beiden Tools auf Top-Niveau. Doch während TwoSeven als kommerzielles Portal mit integriertem Webcam-Chat und Abonnement-Optionen aufgebaut ist, bleibt KoalaSync eine minimalistische, komplett kostenfreie und datenschutzfreundliche Erweiterung. Welcher Dienst besser zu dir passt, erfährst du hier.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Wann TwoSeven die bessere Wahl ist",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven ist die richtige Wahl, wenn du eine <strong>All-in-One-Lösung mit integrierter Webcam und Audio-Chat</strong> direkt im Browser suchst. Wenn du deine Freunde beim Schauen unbedingt sehen möchtest, ohne dafür nebenbei Discord oder Teamspeak laufen zu lassen, bietet TwoSeven diese Integration nativ. Zudem läuft der Dienst für YouTube und einige freie Web-Videoplayer ohne zusätzliche Accounts oder Erweiterungen. Er eignet sich gut für kleine Runden von 2 bis 3 Personen, die sich beim Schauen auch visuell austauschen möchten.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Wann KoalaSync besser passt",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync glänzt durch seine <strong>vollkommene Gebührenfreiheit, Privatsphäre und Einfachheit</strong>:<br><br>• <strong>Keine Bezahlschranken (Paywalls)</strong>: Um bei TwoSeven Premium-Dienste wie Disney+ oder Hulu synchronisiert zu schauen, muss mindestens ein Teilnehmer im Raum TwoSeven kostenpflichtig auf Patreon unterstützen (ab $3/Monat). KoalaSync synchronisiert Netflix, Prime Video, Disney+ und selbstgehostete Server (Jellyfin, Plex, Emby) zu 100 % kostenlos und ohne Einschränkungen.<br>• <strong>Absoluter Datenschutz (Keine Tracker/Werbung)</strong>: TwoSeven ist werbefinanziert und nutzt zahlreiche Tracker von Google, Facebook und Co. KoalaSync hat keine Werbung, keine Tracker und verbindet sich ausschließlich mit dem RAM-basierten Relay-Server.<br>• <strong>Keine Registrierung erforderlich</strong>: Bei TwoSeven müssen alle Teilnehmer ein Konto erstellen und eingeloggt sein. KoalaSync kommt komplett ohne Accounts aus. Einfach installieren, Raumcode eingeben und loslegen.<br>• <strong>Schlank und ressourcenschonend</strong>: Die integrierten Webcam- und Audio-Feeds von TwoSeven belasten die CPU und Internetleitung stark. Da KoalaSync die Kommunikation externen Tools wie Discord überlässt, läuft es extrem flüssig und schont den Laptop-Akku.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "Der wichtigste Unterschied",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven ist eine <strong>kommerzielle Plattform</strong> mit Kontozwang, Werbung, P2P-Webcam-Chat und Patreon-Paywalls für bestimmte Streaming-Dienste. KoalaSync ist ein <strong>kostenloses Open-Source-Utility</strong>, das sich ohne Registrierung, Tracker oder zusätzliche Kosten einfach in deine Browser-Tabs einklinkt, um das ungestörte Schauen im Original-Player zu ermöglichen.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Ehrliche Grenzen",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync bietet <strong>keinen eigenen Webcam- oder Audio-Chat</strong> und setzt voraus, dass ihr bereits über Discord oder ein ähnliches Tool telefoniert. Zudem hat KoalaSync keine eingebaute Chatbox auf der Webseite und ist derzeit nur für Desktop-Browser verfügbar.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Kurz gesagt",
"ALT_TWOSEVEN_SUMMARY_BODY": "Für gemütliche Zweier- oder Dreier-Runden, bei denen man sich unbedingt direkt im Browserfenster über Webcams sehen möchte und bereit ist, für Disney+ ein Patreon-Abo abzuschließen, ist TwoSeven eine nette Option. Für werbefreie, komplett kostenlose und private Filmabende in nativer 4K-Qualität (egal ob Netflix, Prime Video, Disney+ oder Jellyfin) ohne Kontozwang ist KoalaSync die sauberere und sicherere Wahl.",
"ALT_TRY_KOALASYNC": "KoalaSync ausprobieren",
"MOCK_HOST_CONTROL_LABEL": "Host-Steuerung",
"MOCK_HOST_CONTROL_TOGGLE": "Nur ich darf die Wiedergabe steuern",
+39
View File
@@ -235,6 +235,45 @@
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: Which watch party platform fits better?",
"ALT_SCENER_META_DESC": "An honest comparison of KoalaSync and Scener. Discover when Scener's webcam chat wins and why KoalaSync is best for distraction-free movie nights.",
"ALT_SCENER_INTRO": "KoalaSync and Scener approach watch parties from two completely different angles. Scener is a virtual movie theater with built-in video chat and interactive rooms. KoalaSync, on the other hand, is a minimalist, privacy-friendly browser extension that simply synchronizes playback controls. Which tool fits you best depends mostly on how important built-in webcam and chat features are to you.",
"ALT_SCENER_WHEN_SCENER_TITLE": "When Scener is the better choice",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener is a solid choice if you want an <strong>all-in-one social platform</strong> with built-in video and audio chat directly in your browser. Scener creates a virtual room where the player and your friends' webcams are displayed side-by-side. This is ideal for large, public watch parties or virtual streaming events where the social aspect is front and center. However, keep in mind that the free basic version is ad-supported, and Scener locks many features (such as ad-free viewing and unlimited video chat) behind a monthly subscription ($5.79/month or $39.99/year).",
"ALT_SCENER_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync shines when it comes to <strong>video quality, privacy, and simplicity</strong>:<br><br>• <strong>No accounts</strong>: You don't need to register, log in, or manage profiles. Just activate the extension, share a room code, and start watching.<br>• <strong>True native quality (4K/HDR)</strong>: Scener streams compressed video from a virtual cloud server, which can lead to quality loss and lagging. KoalaSync synchronizes the native player directly on your computer, meaning you watch movies in the full resolution of your streaming subscription.<br>• <strong>Low bandwidth usage</strong>: Because only control data (play, pause, timestamps) is transmitted, KoalaSync uses virtually no extra bandwidth. Scener streams the entire video and camera feeds over cloud servers, which can heavily strain slower internet connections and older laptops.<br>• <strong>100% free and ad-free</strong>: No monthly subscription fees, no advertisements, and no trackers.<br>• <strong>Local video files</strong>: Since KoalaSync runs locally, you can even watch your own video files (like MP4) in sync with friends. Just drag and drop the file into a browser tab Scener cannot do this because its player runs in the cloud.",
"ALT_SCENER_MAIN_DIFF_TITLE": "The main difference",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener is a <strong>commercial social network</strong> for watch parties that is powered by virtual cloud browsers and funded through ads and monthly subscriptions. KoalaSync is a <strong>privacy-first, free synchronization utility</strong> that hooks directly into your browser tabs. It leaves voice/video chat to applications like Discord or Teamspeak, focusing entirely on keeping your playback fluid, private, and in its native original quality.",
"ALT_SCENER_LIMITS_TITLE": "Honest limitations",
"ALT_SCENER_LIMITS_BODY": "KoalaSync offers <strong>no built-in chat or webcam support</strong>. It is purely a synchronization tool and requires a separate voice call tool of your choice. Additionally, KoalaSync is currently desktop-only, and local video file compatibility depends entirely on whether your browser natively supports playing the video format and audio codecs.",
"ALT_SCENER_SUMMARY_TITLE": "In short",
"ALT_SCENER_SUMMARY_BODY": "For large watch parties with built-in webcam chat and social features, Scener is the right choice, provided you don't mind ads and premium paywalls. If you want a completely free, ad-free, and distraction-free experience in the native player (including Netflix, Prime Video, Disney+, or local browser files) and you are already in a voice call, KoalaSync is the cleaner and more performant solution.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: Which Netflix party alternative fits better?",
"ALT_KOSMI_META_DESC": "An honest comparison of KoalaSync and Kosmi. Discover why Kosmi's no-extension setup is convenient and when KoalaSync's native video quality wins.",
"ALT_KOSMI_INTRO": "Both KoalaSync and Kosmi offer great ways to watch Netflix, YouTube, and other platforms in sync with friends. However, their underlying technologies are fundamentally different. Kosmi uses virtual cloud browsers that run directly in your web browser without installing extensions. KoalaSync is a lightweight extension that synchronizes your local video player. Which approach fits you best depends on your priorities regarding video quality, convenience, and privacy.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "When Kosmi is the better choice",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi is unbeatable if you want to <strong>avoid installing anything</strong> or want to watch on devices like tablets and smartphones. Because Kosmi runs virtual browsers in the cloud, all it takes to join is a simple web link. Furthermore, Kosmi is an all-in-one hangout platform: in addition to synchronized streaming, you can play multiplayer games (like retro NES/SNES classics or poker) and use the built-in webcam, voice, and text chat. If you want a social game night and watch party without setup, Kosmi is a fantastic solution.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync shines when it comes to <strong>native playback quality, security, and performance</strong>:<br><br>• <strong>No security risks</strong>: With Kosmi, you have to log into your Netflix or Prime account on a remote virtual computer in the cloud. With KoalaSync, you log in securely on the official streaming website in your own browser, just like you normally do. Your passwords never leave your machine.<br>• <strong>Full video quality (4K/HDR)</strong>: Kosmi streams the virtual browser's screen as a compressed video feed, which can result in pixelation and buffering. KoalaSync syncs the native players locally: you enjoy movies in the full, crystal-clear resolution of your subscription.<br>• <strong>Lag-free & bandwidth-friendly</strong>: Since KoalaSync only sends control commands (play/pause/timestamps), it uses almost zero bandwidth. Kosmi constantly streams HD video feeds, which can overwhelm slower connections.<br>• <strong>Local video files</strong>: If you want to watch a private video, just drag and drop the MP4 file into a browser tab and sync it. Kosmi cannot access files on your local hard drive.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "The main difference",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi is a <strong>virtual cloud hangout</strong> that streams a remote browser's screen so no one has to install an extension. KoalaSync is a <strong>local browser sync layer</strong> that hooks directly into the native player on the official streaming website. While Kosmi is more versatile for mini-games and device compatibility, KoalaSync offers a more secure, fluid, and sharp streaming experience in the original player.",
"ALT_KOSMI_LIMITS_TITLE": "Honest limitations",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>requires installing a browser extension</strong> and currently only runs on desktop PCs. It <strong>has no built-in chat or webcams</strong>, as it is designed under the assumption that you are already talking via Discord or other voice tools anyway. It also does not offer built-in games.",
"ALT_KOSMI_SUMMARY_TITLE": "In short",
"ALT_KOSMI_SUMMARY_BODY": "For casual game nights with retro classics and easy access on mobile devices without any installation, Kosmi is ideal. For premium movie nights on Netflix, Prime Video, Disney+, or Plex in full 4K quality, with maximum security and minimal bandwidth impact, KoalaSync is the clear winner.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: Which watch party solution fits better?",
"ALT_TWOSEVEN_META_DESC": "An honest comparison of KoalaSync and TwoSeven. Discover when TwoSeven's built-in webcam wins and why KoalaSync is best for Disney+ and Netflix.",
"ALT_TWOSEVEN_INTRO": "Both KoalaSync and TwoSeven use the same basic approach for watch parties: they synchronize the original video player directly in your browser, rather than streaming a compressed video feed from the cloud. This ensures top-tier video quality for both tools. However, while TwoSeven is a commercial portal with built-in webcam chat and subscription tiers, KoalaSync remains a minimalist, completely free, and privacy-friendly extension. Find out which service fits you best here.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "When TwoSeven is the better choice",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven is the right choice if you want an <strong>all-in-one solution with integrated webcam and audio chat</strong> directly in your browser. If you want to see your friends while watching without having to run Discord or Teamspeak in the background, TwoSeven offers this integration natively. Additionally, it works for YouTube and a few open web video players without extensions. It is well-suited for small groups of 2 to 3 people who want to share a visual connection while viewing.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync shines with its <strong>complete lack of fees, privacy, and simplicity</strong>:<br><br>• <strong>No paywalls</strong>: To watch premium services like Disney+ or Hulu in sync on TwoSeven, at least one room member must support them on Patreon (starting at $3/month). KoalaSync synchronizes Netflix, Prime Video, Disney+, and self-hosted media servers (Jellyfin, Plex, Emby) 100% free with zero restrictions.<br>• <strong>Absolute privacy (No trackers/ads)</strong>: TwoSeven is ad-supported and uses multiple trackers from Google, Facebook, and others. KoalaSync has no ads, no trackers, and communicates exclusively with the RAM-only relay server.<br>• <strong>No registration required</strong>: TwoSeven requires all participants to create an account and log in. KoalaSync is completely account-free. Just install, enter a room code, and start watching.<br>• <strong>Lightweight and resource-friendly</strong>: TwoSeven's integrated webcam and audio feeds place a heavy load on your CPU and network. By leaving communication to tools like Discord, KoalaSync runs extremely smoothly and preserves battery life.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "The main difference",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven is a <strong>commercial platform</strong> with registration requirements, ads, peer-to-peer webcam chats, and Patreon paywalls for specific streaming services. KoalaSync is a <strong>free, open-source utility</strong> that hooks directly into your browser tabs without accounts, trackers, or extra costs, allowing for distraction-free watching in the native player.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Honest limitations",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync offers <strong>no built-in webcam or audio chat</strong> and assumes that you are already on a call via Discord or a similar tool. Additionally, KoalaSync has no built-in chat box overlay and is currently desktop-only.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "In short",
"ALT_TWOSEVEN_SUMMARY_BODY": "For small groups of two or three people who want to see each other via webcams directly in the browser and don't mind supporting a Patreon for Disney+ support, TwoSeven is a nice option. For ad-free, completely free, and private movie nights in native 4K quality (whether Netflix, Prime Video, Disney+, or Jellyfin) without registrations, KoalaSync is the cleaner and safer choice.",
"ALT_TRY_KOALASYNC": "Try KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Host Control",
"MOCK_HOST_CONTROL_TOGGLE": "Only I can control playback",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync no sustituye a una llamada de voz. Si quieres hablar mientras ves el contenido, puedes seguir usando Discord, Teamspeak, Signal, WhatsApp o cualquier otra herramienta que utilices habitualmente.<br><br>Además, cada participante necesita acceder al vídeo o a la página web desde su propio dispositivo. KoalaSync no elude suscripciones, inicios de sesión, DRM, restricciones regionales ni las normas de las plataformas.<br><br>Actualmente solo funciona en navegadores de escritorio, no incluye funciones de chat o voz, y la compatibilidad depende siempre del navegador y del reproductor de vídeo.",
"ALT_SCREEN_SUMMARY_TITLE": "Resumen",
"ALT_SCREEN_SUMMARY_BODY": "Compartir pantalla es la opción más sencilla cuando buscas algo rápido y no te preocupa demasiado la calidad, la privacidad o el control individual. KoalaSync es una mejor alternativa cuando cada persona debe ver el contenido localmente en su propio navegador y se busca una experiencia que realmente se asemeje a verlo juntos.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: ¿Qué solución de fiesta de visualización se adapta mejor?",
"ALT_W2G_META_DESC": "Una comparación honesta entre KoalaSync y Watch2Gether. Descubra cuándo la flexibilidad de KoalaSync es inmejorable y por qué Watch2Gether sigue siendo la mejor opción para YouTube.",
"ALT_W2G_INTRO": "KoalaSync y Watch2Gether resuelven el mismo problema: ver vídeos sincronizados con amigos en línea sin coordinarlos manualmente. Si bien Watch2Gether es uno de los centros más antiguos y populares para noches de películas compartidas, KoalaSync adopta un enfoque liviano y completamente diferente. La herramienta adecuada para usted depende en gran medida de qué y dónde desea mirar.",
"ALT_W2G_WHEN_W2G_TITLE": "Cuando Watch2Gether es la mejor opción",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether es inmejorable para las <strong>fiestas de visualización de YouTube</strong>. Con su lista de reproducción y búsqueda integradas, cualquier persona en la sala puede buscar, agregar y reproducir nuevos videos fácilmente. Todos ven el siguiente video juntos sin problemas.<br><br>Con KoalaSync en YouTube, la reproducción automática predeterminada del sitio toma el control y redirige a cada usuario a un video recomendado diferente. Nuestra función automática del siguiente episodio (\"Episode Lobby\"), que funciona muy bien en Netflix o Disney+, no funciona en YouTube debido a estas recomendaciones dinámicas. Para las noches puramente de YouTube, Watch2Gether es la mejor opción.",
"ALT_W2G_WHEN_KOALA_TITLE": "Cuando KoalaSync se adapta mejor",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync brilla en <strong>servicios de streaming reales</strong> (Netflix, Prime Video, Disney+) y servidores de medios autohospedados (Jellyfin, Plex, Emby). A diferencia de Watch2Gether, que a menudo no puede reproducir ningún contenido premium, KoalaSync sincroniza el reproductor nativo directamente en el sitio web.<br><br>Funciona en casi cualquier sitio con un reproductor de vídeo HTML5 estándar. No es necesario configurar una sala virtual en un sitio de terceros: simplemente active la extensión, únase a un lobby y comience a mirar.",
"ALT_W2G_MAIN_DIFF_TITLE": "La principal diferencia",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether es un <strong>sitio web independiente</strong> con chat integrado, listas de reproducción y soporte para cámara web. KoalaSync es una <strong>extensión de navegador minimalista</strong> que se conecta directamente a las pestañas normales de tu navegador.<br><br>¿Buscas un paquete todo en uno para YouTube con chat integrado? Utilice Watch2Gether. ¿Quieres ver películas en Netflix o en tu propio servidor sin distracciones, en calidad nativa (sin compresión del servidor)? KoalaSync es la solución más limpia.",
"ALT_W2G_LIMITS_TITLE": "Limitaciones honestas",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>no tiene listas de reproducción ni búsqueda de vídeos integradas</strong>. En YouTube, esto significa que la reproducción automática del siguiente vídeo no permanecerá sincronizada.<br><br>Además, <strong>no hay chat integrado</strong> y KoalaSync actualmente solo funciona en navegadores de escritorio. Está diseñado bajo el supuesto de que ya estás hablando a través de Discord, Teamspeak u otras herramientas de voz de todos modos.",
"ALT_W2G_SUMMARY_TITLE": "En breve",
"ALT_W2G_SUMMARY_BODY": "Para sesiones espontáneas de YouTube con listas de reproducción y chat integrado, Watch2Gether es la mejor opción. Para plataformas de streaming premium (como Netflix, Prime Video, Disney+), servidores autohospedados (Jellyfin, Plex, Emby) y máxima flexibilidad del navegador, KoalaSync es la herramienta más adecuada y ligera.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: ¿Qué plataforma de watch party se adapta mejor?",
"ALT_SCENER_META_DESC": "Una comparación honesta de KoalaSync y Scener. Descubra cuándo gana el chat con cámara web de Scener y por qué KoalaSync es mejor para noches de cine sin distracciones.",
"ALT_SCENER_INTRO": "KoalaSync y Scener abordan las fiestas de visualización desde dos ángulos completamente diferentes. Scener es una sala de cine virtual con video chat integrado y salas interactivas. KoalaSync, por otro lado, es una extensión de navegador minimalista y respetuosa con la privacidad que simplemente sincroniza los controles de reproducción. La herramienta que mejor se adapte a sus necesidades depende principalmente de la importancia que tengan para usted las funciones integradas de cámara web y chat.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Cuando Scener es la mejor opción",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener es una opción sólida si desea una <strong>plataforma social todo en uno</strong> con chat de audio y video integrado directamente en su navegador. Scener crea una sala virtual donde el reproductor y las cámaras web de tus amigos se muestran una al lado de la otra. Esto es ideal para grandes fiestas públicas o eventos de transmisión virtual donde el aspecto social está al frente y al centro. Sin embargo, tenga en cuenta que la versión básica gratuita cuenta con publicidad y Scener bloquea muchas funciones (como visualización sin publicidad y video chat ilimitado) detrás de una suscripción mensual ($5,79/mes o $39,99/año).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Cuando KoalaSync se adapta mejor",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync brilla cuando se trata de <strong>calidad de vídeo, privacidad y simplicidad</strong>:<br><br>• <strong>Sin cuentas</strong>: no es necesario registrarse, iniciar sesión ni administrar perfiles. Simplemente active la extensión, comparta un código de sala y comience a mirar.<br>• <strong>Calidad nativa verdadera (4K/HDR)</strong>: Scener transmite video comprimido desde un servidor virtual en la nube, lo que puede provocar pérdida de calidad y retrasos. KoalaSync sincroniza el reproductor nativo directamente en su computadora, lo que significa que puede ver películas en la resolución completa de su suscripción de transmisión.<br>• <strong>Bajo uso de ancho de banda</strong>: debido a que solo se transmiten datos de control (reproducción, pausa, marcas de tiempo), KoalaSync prácticamente no usa ancho de banda adicional. Scener transmite todo el video y las transmisiones de la cámara a través de servidores en la nube, lo que puede sobrecargar las conexiones a Internet más lentas y las computadoras portátiles más antiguas.<br>• <strong>100% gratis y sin publicidad</strong>: sin tarifas de suscripción mensual, sin publicidad ni rastreadores.<br>• <strong>Archivos de video locales</strong>: dado que KoalaSync se ejecuta localmente, incluso puedes ver tus propios archivos de video (como MP4) en sincronización con amigos. Simplemente arrastre y suelte el archivo en una pestaña del navegador; Scener no puede hacer esto porque su reproductor se ejecuta en la nube.",
"ALT_SCENER_MAIN_DIFF_TITLE": "La principal diferencia",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener es una <strong>red social comercial</strong> para grupos de visualización que funciona con navegadores virtuales en la nube y se financia a través de anuncios y suscripciones mensuales. KoalaSync es una <strong>utilidad de sincronización gratuita que prioriza la privacidad</strong> y se conecta directamente a las pestañas de su navegador. Deja el chat de voz/vídeo en manos de aplicaciones como Discord o Teamspeak, centrándose por completo en mantener la reproducción fluida, privada y en su calidad original nativa.",
"ALT_SCENER_LIMITS_TITLE": "Limitaciones honestas",
"ALT_SCENER_LIMITS_BODY": "KoalaSync no ofrece <strong>soporte integrado para chat o cámara web</strong>. Es puramente una herramienta de sincronización y requiere una herramienta de llamada de voz independiente de su elección. Además, KoalaSync actualmente es solo para escritorio y la compatibilidad de archivos de video locales depende completamente de si su navegador admite de forma nativa la reproducción del formato de video y códecs de audio.",
"ALT_SCENER_SUMMARY_TITLE": "En breve",
"ALT_SCENER_SUMMARY_BODY": "Para grandes grupos de visualización con chat con cámara web integrado y funciones sociales, Scener es la opción correcta, siempre que no le importen los anuncios y los muros de pago premium. Si desea una experiencia completamente gratuita, sin publicidad y sin distracciones en el reproductor nativo (incluidos Netflix, Prime Video, Disney+ o archivos del navegador local) y ya está en una llamada de voz, KoalaSync es la solución más limpia y eficaz.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: ¿Qué alternativa de fiesta de Netflix encaja mejor?",
"ALT_KOSMI_META_DESC": "Una comparación honesta de KoalaSync y Kosmi. Descubra por qué la configuración sin extensiones de Kosmi es conveniente y cuándo gana la calidad de video nativa de KoalaSync.",
"ALT_KOSMI_INTRO": "Tanto KoalaSync como Kosmi ofrecen excelentes formas de ver Netflix, YouTube y otras plataformas sincronizadas con amigos. Sin embargo, sus tecnologías subyacentes son fundamentalmente diferentes. Kosmi utiliza navegadores virtuales en la nube que se ejecutan directamente en su navegador web sin instalar extensiones. KoalaSync es una extensión liviana que sincroniza su reproductor de video local. El enfoque que mejor se adapte a sus necesidades depende de sus prioridades en cuanto a calidad de vídeo, comodidad y privacidad.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Cuando Kosmi es la mejor opción",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi es inmejorable si quieres <strong>evitar instalar nada</strong> o quieres mirar en dispositivos como tabletas y teléfonos inteligentes. Debido a que Kosmi ejecuta navegadores virtuales en la nube, todo lo que se necesita para unirse es un simple enlace web. Además, Kosmi es una plataforma de reunión todo en uno: además de la transmisión sincronizada, puedes jugar juegos multijugador (como clásicos retro de NES/SNES o póquer) y usar la cámara web integrada, el chat de voz y de texto. Si quieres una noche de juegos sociales y una fiesta para ver sin configuración, Kosmi es una solución fantástica.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Cuando KoalaSync se adapta mejor",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync brilla cuando se trata de <strong>calidad de reproducción nativa, seguridad y rendimiento</strong>:<br><br>• <strong>Sin riesgos de seguridad</strong>: con Kosmi, debes iniciar sesión en tu cuenta de Netflix o Prime en una computadora virtual remota en la nube. Con KoalaSync, inicias sesión de forma segura en el sitio web oficial de transmisión en tu propio navegador, tal como lo haces normalmente. Sus contraseñas nunca salen de su máquina.<br>• <strong>Calidad de vídeo completa (4K/HDR)</strong>: Kosmi transmite la pantalla del navegador virtual como una señal de vídeo comprimida, lo que puede provocar pixelación y almacenamiento en búfer. KoalaSync sincroniza los reproductores nativos localmente: usted disfruta de las películas con la resolución completa y nítida de su suscripción.<br>• <strong>Sin demoras y compatible con el ancho de banda</strong>: dado que KoalaSync solo envía comandos de control (reproducir/pausar/marcas de tiempo), utiliza casi cero ancho de banda. Kosmi transmite constantemente transmisiones de video HD, lo que puede abrumar las conexiones más lentas.<br>• <strong>Archivos de video locales</strong>: si desea ver un video privado, simplemente arrastre y suelte el archivo MP4 en una pestaña del navegador y sincronícelo. Kosmi no puede acceder a los archivos de su disco duro local.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "La principal diferencia",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi es un <strong>lugar virtual en la nube</strong> que transmite la pantalla de un navegador remoto para que nadie tenga que instalar una extensión. KoalaSync es una <strong>capa de sincronización del navegador local</strong> que se conecta directamente al reproductor nativo en el sitio web oficial de streaming. Si bien Kosmi es más versátil en cuanto a minijuegos y compatibilidad con dispositivos, KoalaSync ofrece una experiencia de transmisión más segura, fluida y nítida en el reproductor original.",
"ALT_KOSMI_LIMITS_TITLE": "Limitaciones honestas",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>requiere la instalación de una extensión del navegador</strong> y actualmente solo se ejecuta en PC de escritorio. <strong>No tiene chat ni cámaras web integrados</strong>, ya que está diseñado bajo el supuesto de que de todos modos ya estás hablando a través de Discord u otras herramientas de voz. Tampoco ofrece juegos integrados.",
"ALT_KOSMI_SUMMARY_TITLE": "En breve",
"ALT_KOSMI_SUMMARY_BODY": "Para noches de juegos casuales con clásicos retro y fácil acceso en dispositivos móviles sin instalación, Kosmi es ideal. Para noches de películas premium en Netflix, Prime Video, Disney+ o Plex en calidad total 4K, con máxima seguridad y mínimo impacto en el ancho de banda, KoalaSync es el claro ganador.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: ¿Qué solución de fiesta de visualización se adapta mejor?",
"ALT_TWOSEVEN_META_DESC": "Una comparación honesta de KoalaSync y TwoSeven. Descubra cuándo gana la cámara web integrada de TwoSeven y por qué KoalaSync es mejor para Disney+ y Netflix.",
"ALT_TWOSEVEN_INTRO": "Tanto KoalaSync como TwoSeven utilizan el mismo enfoque básico para las fiestas de visualización: sincronizan el reproductor de vídeo original directamente en su navegador, en lugar de transmitir un vídeo comprimido desde la nube. Esto garantiza una calidad de vídeo de primer nivel para ambas herramientas. Sin embargo, si bien TwoSeven es un portal comercial con chat con cámara web integrado y niveles de suscripción, KoalaSync sigue siendo una extensión minimalista, completamente gratuita y respetuosa con la privacidad. Descubra aquí qué servicio se adapta mejor a sus necesidades.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Cuando TwoSeven es la mejor opción",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven es la elección correcta si desea una <strong>solución todo en uno con cámara web integrada y chat de audio</strong> directamente en su navegador. Si quieres ver a tus amigos mientras miran sin tener que ejecutar Discord o Teamspeak en segundo plano, TwoSeven ofrece esta integración de forma nativa. Además, funciona para YouTube y algunos reproductores de vídeo web abiertos sin extensiones. Es ideal para grupos pequeños de 2 a 3 personas que quieran compartir una conexión visual mientras miran.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Cuando KoalaSync se adapta mejor",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync brilla por su <strong>falta total de tarifas, privacidad y simplicidad</strong>:<br><br>• <strong>Sin muros de pago</strong>: para ver servicios premium como Disney+ o Hulu sincronizados en TwoSeven, al menos un miembro de la sala debe apoyarlos en Patreon (a partir de $3/mes). KoalaSync sincroniza Netflix, Prime Video, Disney+ y servidores multimedia autohospedados (Jellyfin, Plex, Emby) de forma 100 % gratuita y sin restricciones.<br>• <strong>Privacidad absoluta (sin rastreadores ni anuncios):</strong> TwoSeven cuenta con publicidad y utiliza múltiples rastreadores de Google, Facebook y otros. KoalaSync no tiene anuncios ni rastreadores y se comunica exclusivamente con el servidor de retransmisión de solo RAM.<br>• <strong>No es necesario registrarse</strong>: TwoSeven requiere que todos los participantes creen una cuenta e inicien sesión. KoalaSync no tiene ninguna cuenta. Simplemente instálelo, ingrese un código de sala y comience a mirar.<br>• <strong>Ligero y con pocos recursos</strong>: la cámara web integrada y las transmisiones de audio de TwoSeven suponen una gran carga para su CPU y su red. Al dejar la comunicación en manos de herramientas como Discord, KoalaSync funciona de manera extremadamente fluida y preserva la duración de la batería.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "La principal diferencia",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven es una <strong>plataforma comercial</strong> con requisitos de registro, anuncios, chats con cámara web de igual a igual y muros de pago de Patreon para servicios de transmisión específicos. KoalaSync es una <strong>utilidad gratuita de código abierto</strong> que se conecta directamente a las pestañas de su navegador sin cuentas, rastreadores ni costos adicionales, lo que permite mirar contenido sin distracciones en el reproductor nativo.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Limitaciones honestas",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync no ofrece <strong>cámara web ni chat de audio integrados</strong> y asume que ya estás en una llamada a través de Discord o una herramienta similar. Además, KoalaSync no tiene un cuadro de chat superpuesto incorporado y actualmente es solo para escritorio.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "En breve",
"ALT_TWOSEVEN_SUMMARY_BODY": "Para grupos pequeños de dos o tres personas que quieren verse a través de cámaras web directamente en el navegador y no les importa apoyar a Patreon para Disney+, TwoSeven es una buena opción. Para noches de cine privadas, completamente gratuitas y sin publicidad en calidad nativa 4K (ya sea Netflix, Prime Video, Disney+ o Jellyfin) sin registros, KoalaSync es la opción más limpia y segura.",
"ALT_TRY_KOALASYNC": "Prueba KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Control del anfitrión",
"MOCK_HOST_CONTROL_TOGGLE": "Solo yo puedo controlar la reproducción",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync ne remplace pas un appel vocal. Si vous souhaitez discuter tout en regardant, vous continuez à utiliser Discord, Teamspeak, Signal, WhatsApp ou tout autre outil habituel.<br><br>Chacun doit également pouvoir accéder à la vidéo ou à la page depuis son propre appareil. KoalaSync ne contourne ni les abonnements, ni les identifiants, ni les DRM, ni les restrictions géographiques ou les règles des plateformes.<br><br>L'outil fonctionne actuellement uniquement sur les navigateurs de bureau, ne dispose pas de fonction de chat ou de voix intégrée, et la compatibilité dépend toujours du navigateur et du lecteur vidéo utilisé.",
"ALT_SCREEN_SUMMARY_TITLE": "Résumé",
"ALT_SCREEN_SUMMARY_BODY": "Le partage d'écran est la solution la plus simple si vous cherchez une méthode rapide sans accorder une grande importance à la qualité, à la confidentialité ou au contrôle individuel. KoalaSync est plus adapté lorsque chaque participant doit visionner le contenu localement dans son propre navigateur, pour une expérience se rapprochant davantage d'un véritable visionnage en commun.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether : quelle solution de watch party vous convient le mieux ?",
"ALT_W2G_META_DESC": "Une comparaison honnête entre KoalaSync et Watch2Gether. Découvrez quand la flexibilité de KoalaSync est imbattable et pourquoi Watch2Gether reste le premier choix pour YouTube.",
"ALT_W2G_INTRO": "KoalaSync et Watch2Gether résolvent tous deux le même problème : regarder des vidéos synchronisées avec des amis en ligne sans coordination manuelle. Alors que Watch2Gether est l'un des hubs les plus anciens et les plus populaires pour les soirées cinéma partagées, KoalaSync adopte une approche légère et complètement différente. Le choix de l'outil qui vous convient dépend fortement de ce que vous souhaitez regarder et de l'endroit où vous le souhaitez.",
"ALT_W2G_WHEN_W2G_TITLE": "Quand Watch2Gether est le meilleur choix",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether est imbattable pour les <strong>soirées de visionnage sur YouTube</strong>. Grâce à sa liste de lecture et à sa recherche intégrées, n'importe qui dans la pièce peut facilement trouver, ajouter et lire de nouvelles vidéos. Tout le monde regarde la vidéo suivante ensemble de manière transparente.<br><br>Avec KoalaSync sur YouTube, la lecture automatique par défaut du site prend le relais, redirigeant chaque utilisateur vers une vidéo recommandée différente. Notre fonctionnalité automatique de prochain épisode (« Episode Lobby »), qui fonctionne très bien sur Netflix ou Disney+, ne fonctionne pas sur YouTube en raison de ces recommandations dynamiques. Pour les pures soirées YouTube, Watch2Gether est le meilleur choix.",
"ALT_W2G_WHEN_KOALA_TITLE": "Quand KoalaSync s'adapte mieux",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync brille sur les <strong>vrais services de streaming</strong> (Netflix, Prime Video, Disney+) et les serveurs multimédias auto-hébergés (Jellyfin, Plex, Emby). Contrairement à Watch2Gether, qui ne peut souvent pas lire du contenu premium, KoalaSync synchronise le lecteur natif directement sur le site Web.<br><br>Il fonctionne sur presque tous les sites dotés d'un lecteur vidéo HTML5 standard. Vous n'avez pas besoin de créer une salle virtuelle sur un site tiers : activez simplement l'extension, rejoignez un lobby et commencez à regarder.",
"ALT_W2G_MAIN_DIFF_TITLE": "La principale différence",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether est un <strong>site Web autonome</strong> avec chat, listes de lecture et prise en charge par webcam intégrés. KoalaSync est une <strong>extension de navigateur minimaliste</strong> qui se connecte directement aux onglets normaux de votre navigateur.<br><br>Vous recherchez un package tout-en-un pour YouTube avec chat intégré ? Utilisez Watch2Gether. Vous souhaitez regarder des films sur Netflix ou sur votre propre serveur sans distractions, en qualité native (pas de compression du serveur) ? KoalaSync est la solution la plus propre.",
"ALT_W2G_LIMITS_TITLE": "Limites honnêtes",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>n'a pas de listes de lecture intégrées ni de recherche de vidéos</strong>. Sur YouTube, cela signifie que la lecture automatique de la vidéo suivante ne restera pas synchronisée.<br><br>De plus, il n'y a <strong>pas de chat intégré</strong> et KoalaSync ne fonctionne actuellement que sur les navigateurs de bureau. Il est conçu en supposant que vous parlez déjà via Discord, Teamspeak ou d'autres outils vocaux de toute façon.",
"ALT_W2G_SUMMARY_TITLE": "En bref",
"ALT_W2G_SUMMARY_BODY": "Pour les sessions YouTube spontanées avec listes de lecture et chat intégré, Watch2Gether est le meilleur choix. Pour les plateformes de streaming premium (comme Netflix, Prime Video, Disney+), les serveurs auto-hébergés (Jellyfin, Plex, Emby) et une flexibilité maximale du navigateur, KoalaSync est l'outil le plus adapté et le plus léger.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener : quelle plateforme de watch party convient le mieux ?",
"ALT_SCENER_META_DESC": "Une comparaison honnête de KoalaSync et Scener. Découvrez quand le chat par webcam de Scener l'emporte et pourquoi KoalaSync est le meilleur pour des soirées cinéma sans distraction.",
"ALT_SCENER_INTRO": "KoalaSync et Scener abordent les soirées de visionnage sous deux angles complètement différents. Scener est une salle de cinéma virtuelle avec chat vidéo intégré et salles interactives. KoalaSync, quant à lui, est une extension de navigateur minimaliste et respectueuse de la vie privée qui synchronise simplement les commandes de lecture. Loutil qui vous convient le mieux dépend principalement de limportance pour vous des fonctionnalités de webcam et de chat intégrées.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Quand Scener est le meilleur choix",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener est un choix judicieux si vous souhaitez une <strong>plateforme sociale tout-en-un</strong> avec chat vidéo et audio intégré directement dans votre navigateur. Scener crée une salle virtuelle où les webcams du joueur et de vos amis sont affichées côte à côte. Cest idéal pour les grandes soirées publiques ou les événements virtuels en streaming où laspect social est au premier plan. Cependant, gardez à l'esprit que la version de base gratuite est financée par la publicité et que Scener verrouille de nombreuses fonctionnalités (telles que la visualisation sans publicité et le chat vidéo illimité) derrière un abonnement mensuel (5,79 $/mois ou 39,99 $/an).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Quand KoalaSync s'adapte mieux",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync brille en matière de <strong>qualité vidéo, confidentialité et simplicité</strong> :<br><br>• <strong>Aucun compte</strong> : vous n'avez pas besoin de vous inscrire, de vous connecter ou de gérer des profils. Activez simplement l'extension, partagez un code de salle et commencez à regarder.<br>• <strong>Véritable qualité native (4K/HDR)</strong> : Scener diffuse des vidéos compressées à partir d'un serveur cloud virtuel, ce qui peut entraîner une perte de qualité et un retard. KoalaSync synchronise le lecteur natif directement sur votre ordinateur, ce qui signifie que vous regardez des films dans la pleine résolution de votre abonnement de streaming.<br>• <strong>Faible utilisation de la bande passante</strong> : étant donné que seules les données de contrôle (lecture, pause, horodatage) sont transmises, KoalaSync n'utilise pratiquement aucune bande passante supplémentaire. Scener diffuse l'intégralité des flux vidéo et des caméras sur des serveurs cloud, ce qui peut mettre à rude épreuve les connexions Internet plus lentes et les ordinateurs portables plus anciens.<br>• <strong>100 % gratuit et sans publicité</strong> : pas de frais d'abonnement mensuels, pas de publicité et pas de trackers.<br>• <strong>Fichiers vidéo locaux</strong> : étant donné que KoalaSync fonctionne localement, vous pouvez même regarder vos propres fichiers vidéo (comme MP4) en synchronisation avec vos amis. Faites simplement glisser et déposez le fichier dans un onglet du navigateur Scener ne peut pas le faire car son lecteur fonctionne dans le cloud.",
"ALT_SCENER_MAIN_DIFF_TITLE": "La principale différence",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener est un <strong>réseau social commercial</strong> pour les soirées de visionnage, alimenté par des navigateurs cloud virtuels et financé par des publicités et des abonnements mensuels. KoalaSync est un <strong>utilitaire de synchronisation gratuit et axé sur la confidentialité</strong> qui se connecte directement aux onglets de votre navigateur. Il laisse le chat vocal/vidéo à des applications comme Discord ou Teamspeak, se concentrant entièrement sur le maintien de votre lecture fluide, privée et dans sa qualité d'origine native.",
"ALT_SCENER_LIMITS_TITLE": "Limites honnêtes",
"ALT_SCENER_LIMITS_BODY": "KoalaSync n'offre <strong>pas de support intégré pour le chat ou la webcam</strong>. Il s'agit uniquement d'un outil de synchronisation et nécessite un outil d'appel vocal distinct de votre choix. De plus, KoalaSync est actuellement uniquement disponible sur ordinateur et la compatibilité des fichiers vidéo locaux dépend entièrement de la prise en charge native par votre navigateur de la lecture du format vidéo et des codecs audio.",
"ALT_SCENER_SUMMARY_TITLE": "En bref",
"ALT_SCENER_SUMMARY_BODY": "Pour les grandes soirées de visionnage avec chat par webcam intégré et fonctionnalités sociales, Scener est le bon choix, à condition que les publicités et les paywalls premium ne vous dérangent pas. Si vous souhaitez une expérience entièrement gratuite, sans publicité et sans distraction dans le lecteur natif (y compris Netflix, Prime Video, Disney+ ou les fichiers du navigateur local) et que vous êtes déjà en appel vocal, KoalaSync est la solution la plus propre et la plus performante.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi : Quelle alternative de fête Netflix vous convient le mieux ?",
"ALT_KOSMI_META_DESC": "Une comparaison honnête de KoalaSync et Kosmi. Découvrez pourquoi la configuration sans extension de Kosmi est pratique et quand la qualité vidéo native de KoalaSync l'emporte.",
"ALT_KOSMI_INTRO": "KoalaSync et Kosmi offrent tous deux d'excellents moyens de regarder Netflix, YouTube et d'autres plateformes en synchronisation avec des amis. Cependant, leurs technologies sous-jacentes sont fondamentalement différentes. Kosmi utilise des navigateurs cloud virtuels qui s'exécutent directement dans votre navigateur Web sans installer d'extensions. KoalaSync est une extension légère qui synchronise votre lecteur vidéo local. L'approche qui vous convient le mieux dépend de vos priorités en matière de qualité vidéo, de commodité et de confidentialité.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Quand Kosmi est le meilleur choix",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi est imbattable si vous voulez <strong>éviter d'installer quoi que ce soit</strong> ou si vous souhaitez regarder sur des appareils comme les tablettes et les smartphones. Étant donné que Kosmi exécute des navigateurs virtuels dans le cloud, il suffit pour s'inscrire d'un simple lien Web. De plus, Kosmi est une plate-forme de rencontre tout-en-un : en plus du streaming synchronisé, vous pouvez jouer à des jeux multijoueurs (comme les classiques rétro NES/SNES ou le poker) et utiliser la webcam, le chat vocal et textuel intégrés. Si vous souhaitez organiser une soirée de jeux sociaux et regarder une soirée sans configuration, Kosmi est une solution fantastique.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Quand KoalaSync s'adapte mieux",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync brille en matière de <strong>qualité de lecture native, sécurité et performances</strong> :<br><br>• <strong>Aucun risque de sécurité</strong> : avec Kosmi, vous devez vous connecter à votre compte Netflix ou Prime sur un ordinateur virtuel distant dans le cloud. Avec KoalaSync, vous vous connectez en toute sécurité sur le site officiel de streaming dans votre propre navigateur, comme vous le faites habituellement. Vos mots de passe ne quittent jamais votre ordinateur.<br>• <strong>Qualité vidéo complète (4K/HDR)</strong> : Kosmi diffuse l'écran du navigateur virtuel sous forme de flux vidéo compressé, ce qui peut entraîner une pixellisation et une mise en mémoire tampon. KoalaSync synchronise les lecteurs natifs localement : vous profitez de films dans la résolution complète et cristalline de votre abonnement.<br>• <strong>Sans décalage et respectueux de la bande passante</strong> : étant donné que KoalaSync envoie uniquement des commandes de contrôle (lecture/pause/horodatage), il n'utilise presque aucune bande passante. Kosmi diffuse constamment des flux vidéo HD, ce qui peut surcharger les connexions plus lentes.<br>• <strong>Fichiers vidéo locaux</strong> : si vous souhaitez regarder une vidéo privée, faites simplement glisser et déposez le fichier MP4 dans un onglet du navigateur et synchronisez-le. Kosmi ne peut pas accéder aux fichiers sur votre disque dur local.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "La principale différence",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi est un <strong>hangout virtuel dans le cloud</strong> qui diffuse l'écran d'un navigateur distant afin que personne n'ait besoin d'installer une extension. KoalaSync est une <strong>couche de synchronisation du navigateur local</strong> qui se connecte directement au lecteur natif sur le site officiel de streaming. Alors que Kosmi est plus polyvalent pour les mini-jeux et la compatibilité des appareils, KoalaSync offre une expérience de streaming plus sécurisée, fluide et plus précise dans le lecteur d'origine.",
"ALT_KOSMI_LIMITS_TITLE": "Limites honnêtes",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>nécessite l'installation d'une extension de navigateur</strong> et ne fonctionne actuellement que sur les ordinateurs de bureau. Il <strong>n'a pas de chat ni de webcams intégrés</strong>, car il est conçu en supposant que vous parlez déjà via Discord ou d'autres outils vocaux de toute façon. Il ne propose pas non plus de jeux intégrés.",
"ALT_KOSMI_SUMMARY_TITLE": "En bref",
"ALT_KOSMI_SUMMARY_BODY": "Pour des soirées de jeux décontractées avec des classiques rétro et un accès facile sur les appareils mobiles sans aucune installation, Kosmi est idéal. Pour les soirées cinéma premium sur Netflix, Prime Video, Disney+ ou Plex en qualité 4K complète, avec une sécurité maximale et un impact minimal sur la bande passante, KoalaSync est clairement le gagnant.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven : quelle solution de soirée de surveillance convient le mieux ?",
"ALT_TWOSEVEN_META_DESC": "Une comparaison honnête de KoalaSync et TwoSeven. Découvrez quand la webcam intégrée de TwoSeven gagne et pourquoi KoalaSync est le meilleur pour Disney+ et Netflix.",
"ALT_TWOSEVEN_INTRO": "KoalaSync et TwoSeven utilisent la même approche de base pour les séances de visionnage : ils synchronisent le lecteur vidéo d'origine directement dans votre navigateur, plutôt que de diffuser un flux vidéo compressé depuis le cloud. Cela garantit une qualité vidéo de premier ordre pour les deux outils. Cependant, même si TwoSeven est un portail commercial avec chat par webcam et niveaux d'abonnement intégrés, KoalaSync reste une extension minimaliste, entièrement gratuite et respectueuse de la vie privée. Découvrez ici quel service vous convient le mieux.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Quand TwoSeven est le meilleur choix",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven est le bon choix si vous souhaitez une <strong>solution tout-en-un avec webcam et chat audio intégrés</strong> directement dans votre navigateur. Si vous souhaitez voir vos amis tout en regardant sans avoir à exécuter Discord ou Teamspeak en arrière-plan, TwoSeven propose cette intégration de manière native. De plus, il fonctionne pour YouTube et quelques lecteurs vidéo Web ouverts sans extensions. Il convient bien aux petits groupes de 2 à 3 personnes qui souhaitent partager une connexion visuelle tout en visionnant.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Quand KoalaSync s'adapte mieux",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync brille par son <strong>absence totale de frais, de confidentialité et de simplicité</strong> :<br><br>• <strong>Aucun paywall</strong> : pour regarder des services premium comme Disney+ ou Hulu en synchronisation sur TwoSeven, au moins un membre de la salle doit les soutenir sur Patreon (à partir de 3 $/mois). KoalaSync synchronise Netflix, Prime Video, Disney+ et les serveurs multimédias auto-hébergés (Jellyfin, Plex, Emby) de manière 100 % gratuite et sans aucune restriction.<br>• <strong>Confidentialité absolue (pas de trackers/publicités)</strong> : TwoSeven est financé par la publicité et utilise plusieurs trackers de Google, Facebook et autres. KoalaSync n'a pas de publicité, pas de tracker et communique exclusivement avec le serveur relais RAM uniquement.<br>• <strong>Aucune inscription requise</strong> : TwoSeven demande à tous les participants de créer un compte et de se connecter. KoalaSync est totalement sans compte. Il vous suffit de l'installer, de saisir un code de pièce et de commencer à regarder.<br>• <strong>Léger et respectueux des ressources</strong> : la webcam et les flux audio intégrés de TwoSeven imposent une lourde charge sur votre processeur et votre réseau. En laissant la communication à des outils comme Discord, KoalaSync fonctionne de manière extrêmement fluide et préserve la durée de vie de la batterie.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "La principale différence",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven est une <strong>plate-forme commerciale</strong> avec des conditions d'inscription, des publicités, des discussions par webcam peer-to-peer et des paywalls Patreon pour des services de streaming spécifiques. KoalaSync est un <strong>utilitaire open source gratuit</strong> qui se connecte directement aux onglets de votre navigateur sans compte, tracker ou frais supplémentaires, permettant un visionnage sans distraction dans le lecteur natif.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Limites honnêtes",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync n'offre <strong>pas de webcam ni de chat audio intégré</strong> et suppose que vous êtes déjà en communication via Discord ou un outil similaire. De plus, KoalaSync n'a pas de superposition de boîte de discussion intégrée et est actuellement uniquement disponible sur ordinateur.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "En bref",
"ALT_TWOSEVEN_SUMMARY_BODY": "Pour les petits groupes de deux ou trois personnes qui souhaitent se voir via des webcams directement dans le navigateur et qui ne craignent pas de prendre en charge le support Patreon pour Disney+, TwoSeven est une option intéressante. Pour des soirées cinéma sans publicité, entièrement gratuites et privées en qualité 4K native (que ce soit Netflix, Prime Video, Disney+ ou Jellyfin) sans inscription, KoalaSync est le choix le plus propre et le plus sûr.",
"ALT_TRY_KOALASYNC": "Essayer KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Contrôle de l'hôte",
"MOCK_HOST_CONTROL_TOGGLE": "Seul moi peut contrôler la lecture",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync non sostituisce una chiamata vocale. Se volete parlare mentre guardate il contenuto, potete continuare a usare Discord, Teamspeak, Signal, WhatsApp o qualsiasi altro strumento abituale.<br><br>Ciascun partecipante deve inoltre poter accedere al video o alla pagina dal proprio dispositivo. KoalaSync non aggira abbonamenti, accessi, DRM, restrizioni geografiche o regole delle piattaforme.<br><br>Al momento è utilizzabile solo tramite browser desktop, non dispone di funzioni di chat o voce integrate e la compatibilità dipende sempre dal browser e dal lettore video.",
"ALT_SCREEN_SUMMARY_TITLE": "Riepilogo",
"ALT_SCREEN_SUMMARY_BODY": "La condivisione dello schermo è l'opzione più semplice quando si cerca una soluzione rapida e non si dà molta importanza alla qualità, alla privacy o al controllo individuale. KoalaSync è la scelta ideale quando tutti devono guardare il contenuto localmente sul proprio browser, offrendo un'esperienza che ricorda più da vicino la visione condivisa reale.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: quale soluzione per watch party è più adatta?",
"ALT_W2G_META_DESC": "Un confronto onesto tra KoalaSync e Watch2Gether. Scopri quando la flessibilità di KoalaSync è imbattibile e perché Watch2Gether è ancora la scelta migliore per YouTube.",
"ALT_W2G_INTRO": "KoalaSync e Watch2Gether risolvono entrambi lo stesso problema: guardare video sincronizzati con gli amici online senza coordinarsi manualmente. Mentre Watch2Gether è uno degli hub più antichi e popolari per le serate di cinema condivise, KoalaSync adotta un approccio completamente diverso e leggero. Lo strumento giusto per te dipende in larga misura da cosa e dove vuoi guardare.",
"ALT_W2G_WHEN_W2G_TITLE": "Quando Watch2Gether è la scelta migliore",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether è imbattibile per i <strong>watch party di YouTube</strong>. Grazie alla playlist e alla ricerca integrate, chiunque nella stanza può trovare, aggiungere e riprodurre facilmente nuovi video. Tutti guardano insieme il video successivo senza interruzioni.<br><br>Con KoalaSync su YouTube, la riproduzione automatica predefinita del sito prende il sopravvento, reindirizzando ogni utente a un video consigliato diverso. La nostra funzione automatica per l'episodio successivo (\"Lobby episodi\"), che funziona perfettamente su Netflix o Disney+, non funziona su YouTube a causa di questi consigli dinamici. Per le serate puramente YouTube, Watch2Gether è la scelta migliore.",
"ALT_W2G_WHEN_KOALA_TITLE": "Quando KoalaSync si adatta meglio",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync eccelle sui <strong>servizi di streaming reali</strong> (Netflix, Prime Video, Disney+) e sui server multimediali self-hosted (Jellyfin, Plex, Emby). A differenza di Watch2Gether, che spesso non può riprodurre affatto contenuti premium, KoalaSync sincronizza il lettore nativo direttamente sul sito web.<br><br>Funziona su quasi tutti i siti con un lettore video HTML5 standard. Non è necessario configurare una stanza virtuale su un sito di terze parti: basta attivare l'estensione, unirsi a una lobby e iniziare a guardare.",
"ALT_W2G_MAIN_DIFF_TITLE": "La differenza principale",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether è un <strong>sito web autonomo</strong> con chat, playlist e supporto webcam integrati. KoalaSync è un'<strong>estensione del browser minimalista</strong> che si collega direttamente alle normali schede del browser.<br><br>Cerchi un pacchetto tutto in uno per YouTube con chat integrata? Usa Watch2Gether. Vuoi guardare film su Netflix o sul tuo server senza distrazioni, in qualità nativa (senza compressione del server)? KoalaSync è la soluzione più pulita.",
"ALT_W2G_LIMITS_TITLE": "Limitazioni oneste",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>non dispone di playlist integrate o ricerca video</strong>. Su YouTube, ciò significa che la riproduzione automatica del video successivo non rimarrà sincronizzata.<br><br>Inoltre, <strong>non è presente una chat integrata</strong> e KoalaSync attualmente funziona solo sui browser desktop. È progettato partendo dal presupposto che tu stia già parlando tramite Discord, Teamspeak o comunque altri strumenti vocali.",
"ALT_W2G_SUMMARY_TITLE": "Insomma",
"ALT_W2G_SUMMARY_BODY": "Per sessioni YouTube spontanee con playlist e chat integrata, Watch2Gether è la scelta migliore. Per piattaforme di streaming premium (come Netflix, Prime Video, Disney+), server self-hosted (Jellyfin, Plex, Emby) e la massima flessibilità del browser, KoalaSync è lo strumento più adatto e leggero.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: quale piattaforma di watch party si adatta meglio?",
"ALT_SCENER_META_DESC": "Un confronto onesto tra KoalaSync e Scener. Scopri quando vince la chat webcam di Scener e perché KoalaSync è la soluzione migliore per serate di cinema senza distrazioni.",
"ALT_SCENER_INTRO": "KoalaSync e Scener si avvicinano alle feste da due angolazioni completamente diverse. Scener è un cinema virtuale con chat video integrata e stanze interattive. KoalaSync, d'altra parte, è un'estensione del browser minimalista e rispettosa della privacy che sincronizza semplicemente i controlli di riproduzione. Lo strumento più adatto a te dipende principalmente da quanto siano importanti per te le funzionalità di webcam e chat integrate.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Quando Scener è la scelta migliore",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener è una scelta solida se desideri una <strong>piattaforma social tutto in uno</strong> con chat audio e video integrata direttamente nel tuo browser. Scener crea una stanza virtuale in cui il giocatore e le webcam dei tuoi amici vengono visualizzati fianco a fianco. Questo è l'ideale per grandi feste pubbliche o eventi di streaming virtuale in cui l'aspetto sociale è al centro dell'attenzione. Tuttavia, tieni presente che la versione base gratuita è supportata dalla pubblicità e Scener blocca molte funzionalità (come la visualizzazione senza pubblicità e la chat video illimitata) dietro un abbonamento mensile ($ 5,79 al mese o $ 39,99 all'anno).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Quando KoalaSync si adatta meglio",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync eccelle quando si tratta di <strong>qualità video, privacy e semplicità</strong>:<br><br>• <strong>Nessun account</strong>: non è necessario registrarsi, accedere o gestire i profili. Basta attivare l'estensione, condividere un codice della stanza e iniziare a guardare.<br>• <strong>Qualità nativa reale (4K/HDR)</strong>: Scener trasmette in streaming video compressi da un server cloud virtuale, il che può portare a perdita di qualità e ritardi. KoalaSync sincronizza il lettore nativo direttamente sul tuo computer, il che significa che guardi i film alla massima risoluzione del tuo abbonamento di streaming.<br>• <strong>Basso utilizzo della larghezza di banda</strong>: poiché vengono trasmessi solo i dati di controllo (riproduzione, pausa, timestamp), KoalaSync non utilizza praticamente alcuna larghezza di banda aggiuntiva. Scener trasmette in streaming l'intero video e i feed della fotocamera su server cloud, che possono mettere a dura prova le connessioni Internet più lente e i laptop più vecchi.<br>• <strong>100% gratuito e senza pubblicità</strong>: nessun costo di abbonamento mensile, nessuna pubblicità e nessun tracker.<br>• <strong>File video locali</strong>: poiché KoalaSync viene eseguito localmente, puoi persino guardare i tuoi file video (come MP4) sincronizzati con gli amici. Basta trascinare e rilasciare il file in una scheda del browser: Scener non può farlo perché il suo lettore viene eseguito nel cloud.",
"ALT_SCENER_MAIN_DIFF_TITLE": "La differenza principale",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener è un <strong>social network commerciale</strong> per watch party basato su browser cloud virtuali e finanziato tramite annunci e abbonamenti mensili. KoalaSync è un'<strong>utilità di sincronizzazione gratuita, attenta alla privacy</strong> che si collega direttamente alle schede del tuo browser. Lascia la chat vocale/video ad applicazioni come Discord o Teamspeak, concentrandosi interamente sul mantenere la riproduzione fluida, privata e nella sua qualità originale nativa.",
"ALT_SCENER_LIMITS_TITLE": "Limitazioni oneste",
"ALT_SCENER_LIMITS_BODY": "KoalaSync non offre <strong>nessun supporto integrato per chat o webcam</strong>. È puramente uno strumento di sincronizzazione e richiede uno strumento di chiamata vocale separato a tua scelta. Inoltre, KoalaSync è attualmente solo desktop e la compatibilità dei file video locali dipende interamente dal fatto che il tuo browser supporti nativamente la riproduzione del formato video e dei codec audio.",
"ALT_SCENER_SUMMARY_TITLE": "Insomma",
"ALT_SCENER_SUMMARY_BODY": "Per i grandi gruppi di spettatori con chat webcam integrata e funzionalità social, Scener è la scelta giusta, a condizione che non ti dispiaccia la pubblicità e i paywall premium. Se desideri un'esperienza completamente gratuita, senza pubblicità e senza distrazioni nel lettore nativo (inclusi Netflix, Prime Video, Disney+ o file del browser locale) e stai già effettuando una chiamata vocale, KoalaSync è la soluzione più pulita e performante.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: quale alternativa alla festa Netflix si adatta meglio?",
"ALT_KOSMI_META_DESC": "Un confronto onesto tra KoalaSync e Kosmi. Scopri perché la configurazione senza estensione di Kosmi è conveniente e quando vince la qualità video nativa di KoalaSync.",
"ALT_KOSMI_INTRO": "Sia KoalaSync che Kosmi offrono ottimi modi per guardare Netflix, YouTube e altre piattaforme in sincronia con gli amici. Tuttavia, le tecnologie sottostanti sono fondamentalmente diverse. Kosmi utilizza browser cloud virtuali che vengono eseguiti direttamente nel tuo browser web senza installare estensioni. KoalaSync è un'estensione leggera che sincronizza il tuo lettore video locale. L'approccio più adatto a te dipende dalle tue priorità in termini di qualità video, comodità e privacy.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Quando Kosmi è la scelta migliore",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi è imbattibile se vuoi <strong>evitare di installare nulla</strong> o vuoi guardare su dispositivi come tablet e smartphone. Poiché Kosmi esegue browser virtuali nel cloud, per aderire è sufficiente un semplice collegamento Web. Inoltre, Kosmi è una piattaforma di ritrovo all-in-one: oltre allo streaming sincronizzato, puoi giocare a giochi multiplayer (come i classici retrò NES/SNES o il poker) e utilizzare la webcam integrata, la voce e la chat di testo. Se vuoi una serata di gioco sociale e guardare una festa senza installazione, Kosmi è una soluzione fantastica.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Quando KoalaSync si adatta meglio",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync eccelle quando si tratta di <strong>qualità di riproduzione, sicurezza e prestazioni native</strong>:<br><br>• <strong>Nessun rischio per la sicurezza</strong>: con Kosmi, devi accedere al tuo account Netflix o Prime su un computer virtuale remoto nel cloud. Con KoalaSync, accedi in modo sicuro al sito ufficiale di streaming nel tuo browser, proprio come fai normalmente. Le tue password non lasciano mai il tuo computer.<br>• <strong>Qualità video completa (4K/HDR)</strong>: Kosmi trasmette in streaming lo schermo del browser virtuale come feed video compresso, il che può provocare pixelizzazione e buffering. KoalaSync sincronizza i lettori nativi localmente: potrai goderti i film con la risoluzione completa e cristallina del tuo abbonamento.<br>• <strong>Senza ritardi e con larghezza di banda ridotta</strong>: poiché KoalaSync invia solo comandi di controllo (riproduzione/pausa/timestamp), utilizza quasi zero larghezza di banda. Kosmi trasmette costantemente in streaming feed video HD, che possono sovraccaricare le connessioni più lente.<br>• <strong>File video locali</strong>: se desideri guardare un video privato, trascina e rilascia il file MP4 in una scheda del browser e sincronizzalo. Kosmi non può accedere ai file sul tuo disco rigido locale.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "La differenza principale",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi è un <strong>hangout virtuale sul cloud</strong> che trasmette in streaming lo schermo di un browser remoto, quindi nessuno deve installare un'estensione. KoalaSync è un <strong>livello di sincronizzazione del browser locale</strong> che si collega direttamente al player nativo sul sito web di streaming ufficiale. Mentre Kosmi è più versatile per quanto riguarda i minigiochi e la compatibilità dei dispositivi, KoalaSync offre un'esperienza di streaming più sicura, fluida e nitida nel lettore originale.",
"ALT_KOSMI_LIMITS_TITLE": "Limitazioni oneste",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>richiede l'installazione di un'estensione del browser</strong> e attualmente funziona solo su PC desktop. <strong>Non ha chat o webcam integrate</strong>, poiché è progettato partendo dal presupposto che tu stia già parlando tramite Discord o altri strumenti vocali. Inoltre non offre giochi integrati.",
"ALT_KOSMI_SUMMARY_TITLE": "Insomma",
"ALT_KOSMI_SUMMARY_BODY": "Per serate di gioco informali con classici retrò e un facile accesso su dispositivi mobili senza alcuna installazione, Kosmi è l'ideale. Per serate di cinema premium su Netflix, Prime Video, Disney+ o Plex in qualità 4K completa, con la massima sicurezza e un impatto minimo sulla larghezza di banda, KoalaSync è il chiaro vincitore.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: quale soluzione di watch party è più adatta?",
"ALT_TWOSEVEN_META_DESC": "Un confronto onesto tra KoalaSync e TwoSeven. Scopri quando vince la webcam integrata di TwoSeven e perché KoalaSync è la soluzione migliore per Disney+ e Netflix.",
"ALT_TWOSEVEN_INTRO": "Sia KoalaSync che TwoSeven utilizzano lo stesso approccio di base per i watch party: sincronizzano il lettore video originale direttamente nel browser, anziché eseguire lo streaming di un feed video compresso dal cloud. Ciò garantisce una qualità video di alto livello per entrambi gli strumenti. Tuttavia, mentre TwoSeven è un portale commerciale con chat webcam integrata e livelli di abbonamento, KoalaSync rimane un'estensione minimalista, completamente gratuita e rispettosa della privacy. Scopri qui il servizio più adatto a te.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Quando TwoSeven è la scelta migliore",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven è la scelta giusta se desideri una <strong>soluzione all-in-one con webcam e chat audio integrate</strong> direttamente nel tuo browser. Se vuoi vedere i tuoi amici mentre guardi senza dover eseguire Discord o Teamspeak in background, TwoSeven offre questa integrazione in modo nativo. Inoltre, funziona con YouTube e alcuni lettori video Web aperti senza estensioni. È adatto a piccoli gruppi di 2 o 3 persone che desiderano condividere una connessione visiva durante la visione.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Quando KoalaSync si adatta meglio",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync brilla per la sua <strong>totale assenza di costi, privacy e semplicità</strong>:<br><br>• <strong>Nessun paywall</strong>: per guardare servizi premium come Disney+ o Hulu in sincronia su TwoSeven, almeno un membro della stanza deve supportarli su Patreon (a partire da $ 3/mese). KoalaSync sincronizza Netflix, Prime Video, Disney+ e server multimediali self-hosted (Jellyfin, Plex, Emby) in modo gratuito al 100% e senza restrizioni.<br>• <strong>Privacy assoluta (nessun tracker/annuncio)</strong>: TwoSeven supporta la pubblicità e utilizza più tracker di Google, Facebook e altri. KoalaSync non ha pubblicità, né tracker e comunica esclusivamente con il server di inoltro solo RAM.<br>• <strong>Non è richiesta alcuna registrazione</strong>: TwoSeven richiede a tutti i partecipanti di creare un account ed effettuare l'accesso. KoalaSync è completamente privo di account. Basta installarlo, inserire il codice della stanza e iniziare a guardare.<br>• <strong>Leggero e di facile utilizzo</strong>: la webcam integrata e i feed audio di TwoSeven mettono a dura prova la CPU e la rete. Lasciando la comunicazione a strumenti come Discord, KoalaSync funziona in modo estremamente fluido e preserva la durata della batteria.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "La differenza principale",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven è una <strong>piattaforma commerciale</strong> con requisiti di registrazione, annunci, chat webcam peer-to-peer e paywall Patreon per servizi di streaming specifici. KoalaSync è un'<strong>utilità gratuita e open source</strong> che si collega direttamente alle schede del tuo browser senza account, tracker o costi aggiuntivi, consentendo una visione senza distrazioni nel lettore nativo.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Limitazioni oneste",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync non offre <strong>nessuna webcam integrata o chat audio</strong> e presuppone che tu sia già impegnato in una chiamata tramite Discord o uno strumento simile. Inoltre, KoalaSync non ha una finestra di chat incorporata ed è attualmente solo desktop.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Insomma",
"ALT_TWOSEVEN_SUMMARY_BODY": "Per piccoli gruppi di due o tre persone che vogliono vedersi tramite webcam direttamente nel browser e non hanno problemi a supportare Patreon per Disney+, TwoSeven è una buona opzione. Per serate di cinema private, completamente gratuite e senza pubblicità in qualità 4K nativa (che si tratti di Netflix, Prime Video, Disney+ o Jellyfin) senza registrazioni, KoalaSync è la scelta più pulita e sicura.",
"ALT_TRY_KOALASYNC": "Prova KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Controllo host",
"MOCK_HOST_CONTROL_TOGGLE": "Solo io posso controllare la riproduzione",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSyncは音声通話の代わりになるものではありません。視聴しながら会話をする場合は、Discord、TeamSpeak、Signal、WhatsAppなど、普段お使いのツールをそのまま利用します。<br><br>また、参加者全員がそれぞれのデバイスでその動画やページにアクセスできる必要があります。KoalaSyncは、サブスクリプション、ログイン、DRM(デジタル著作権管理)、地域制限、プラットフォームの利用規約などを回避するものではありません。<br><br>現在はデスクトップ版ブラウザのみに対応しており、チャットや音声通話機能は内蔵されていません。また、動作の可否は使用するブラウザや動画プレーヤーに依存します。",
"ALT_SCREEN_SUMMARY_TITLE": "概要",
"ALT_SCREEN_SUMMARY_BODY": "画質やプライバシー、個別の操作性をあまり気にせず、手軽に済ませたい場合は「画面共有」が最も簡単な選択肢です。一方、参加者それぞれが自身のブラウザで動画を再生し、実際に同じ空間で一緒に視聴しているような感覚を重視するなら、KoalaSyncの方が適しています。",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync Watch2Gether: どちらのウォッチ パーティー ソリューションがより適していますか?",
"ALT_W2G_META_DESC": "KoalaSync Watch2Gether の正直な比較。 KoalaSync の柔軟性が優れている理由と、Watch2Gether が YouTube にとって依然としてトップの選択肢である理由をご覧ください。",
"ALT_W2G_INTRO": "KoalaSync Watch2Gether は両方とも同じ問題を解決します。つまり、手動で調整することなく、オンラインで友達と同期してビデオを視聴できます。 Watch2Gether は映画鑑賞を共有するための最も古く、最も人気のあるハブの 1 つですが、KoalaSync はまったく異なる軽量のアプローチを採用しています。どのツールがあなたに適しているかは、何をどこで見たいかによって大きく異なります。",
"ALT_W2G_WHEN_W2G_TITLE": "Watch2Gether がより良い選択である場合",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether は<strong>YouTube ウォッチ パーティー</strong>にとって無敵です。内蔵のプレイリストと検索により、部屋にいる誰もが新しいビデオを簡単に検索、追加、再生できます。全員が一緒にシームレスに次の動画を視聴します。<br><br>YouTube の KoalaSync を使用すると、サイトのデフォルトの自動再生が引き継ぎ、各ユーザーを別のおすすめ動画にリダイレクトします。自動次エピソード機能 (「エピソード ロビー」) は、Netflix Disney+ ではうまく機能しますが、こうした動的な推奨事項のため、YouTube では機能しません。純粋に YouTube の夜を楽しみたい場合は、Watch2Gether が最適です。",
"ALT_W2G_WHEN_KOALA_TITLE": "KoalaSync がより適切にフィットすると",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync は<strong>実際のストリーミング サービス</strong> (NetflixPrime VideoDisney+) および自己ホスト型メディア サーバー (JellyfinPlexEmby) で威力を発揮します。プレミアム コンテンツをまったく再生できないことが多い Watch2Gether とは異なり、KoalaSync はウェブサイト上でネイティブ プレーヤーを直接同期します。<br><br>標準の HTML5 ビデオ プレーヤーを備えたほぼすべてのサイトで動作します。サードパーティのサイトに仮想ルームを設定する必要はありません。拡張機能をアクティブにしてロビーに参加し、視聴を開始するだけです。",
"ALT_W2G_MAIN_DIFF_TITLE": "主な違い",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether は、チャット、プレイリスト、Web カメラのサポートが組み込まれた<strong>スタンドアロン Web サイト</strong>です。 KoalaSync は、通常のブラウザ タブに直接接続する<strong>シンプルなブラウザ拡張機能</strong>です。<br><br>チャットが組み込まれた YouTube 用のオールインワン パッケージをお探しですか? Watch2Gether を使用します。 Netflix または独自のサーバーで、気が散ることなく、ネイティブ品質 (サーバー圧縮なし) で映画を視聴したいですか? KoalaSync はよりクリーンなソリューションです。",
"ALT_W2G_LIMITS_TITLE": "正直な限界",
"ALT_W2G_LIMITS_BODY": "KoalaSync には<strong>プレイリストやビデオ検索が組み込まれていません</strong> YouTube では、これは、次のビデオの自動再生の同期が維持されないことを意味します。<br><br>さらに、<strong>組み込みのチャットはありません</strong>。また、KoalaSync は現在デスクトップ ブラウザでのみ動作します。とにかく、DiscordTeamspeak、またはその他の音声ツールを介してすでに会話しているという前提に基づいて設計されています。",
"ALT_W2G_SUMMARY_TITLE": "要するに",
"ALT_W2G_SUMMARY_BODY": "プレイリストと組み込みチャットを使用した自発的な YouTube セッションには、Watch2Gether が最適な選択です。プレミアム ストリーミング プラットフォーム (NetflixPrime VideoDisney+ など)、セルフホスト サーバー (JellyfinPlexEmby)、お​​よびブラウザの柔軟性を最大限に高めるには、KoalaSync がより適切で軽量なツールです。",
"ALT_SCENER_TITLE": "KoalaSync と Scener: どちらのウォッチ パーティー プラットフォームがより適していますか?",
"ALT_SCENER_META_DESC": "KoalaSync と Scener の正直な比較。 Scener の Web カメラ チャットが最適なタイミングと、気を散らすことなく映画鑑賞に KoalaSync が最適な理由をご確認ください。",
"ALT_SCENER_INTRO": "KoalaSync と Scener は、まったく異なる 2 つの角度からウォッチ パーティーにアプローチします。 Scener は、ビデオ チャットとインタラクティブ ルームが組み込まれた仮想映画館です。一方、KoalaSync は、再生コントロールを単純に同期する、最小限のプライバシーに配慮したブラウザ拡張機能です。どのツールがあなたに最適であるかは、主に、内蔵の Web カメラとチャット機能があなたにとってどれだけ重要であるかによって決まります。",
"ALT_SCENER_WHEN_SCENER_TITLE": "Scener がより良い選択である場合",
"ALT_SCENER_WHEN_SCENER_BODY": "ブラウザにビデオとオーディオのチャットが直接組み込まれている<strong>オールインワンのソーシャル プラットフォーム</strong>が必要な場合は、Scener が確実な選択肢です。 Scener は、プレーヤーと友達の Web カメラが並べて表示される仮想ルームを作成します。これは、ソーシャルな側面が中心となる大規模な公開ウォッチ パーティーや仮想ストリーミング イベントに最適です。ただし、無料の基本バージョンは広告でサポートされており、Scener では月額サブスクリプション (月額 5.79 ドルまたは年間 39.99 ドル) を支払うと、多くの機能 (広告なしの視聴や無制限のビデオ チャットなど) がロックされること注意してください。",
"ALT_SCENER_WHEN_KOALA_TITLE": "KoalaSync がより適切にフィットすると",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync は、<strong>ビデオ品質、プライバシー、 シンプルさ</strong>という点で優れています。<br><br>• <strong>アカウントなし</strong>: 登録、ログイン、プロファイルの管理は必要ありません。拡張機能を有効にしてルーム コードを共有し、視聴を開始するだけです。<br>• <strong>真のネイティブ品質 (4K/HDR)</strong>: Scener は仮想クラウド サーバーから圧縮ビデオをストリーミングしますが、これにより品質の低下や遅延が発生する可能性があります。 KoalaSync は、ネイティブ プレーヤーをコンピュータ上で直接同期します。つまり、ストリーング サブスクリプションのフル解像度で映画を視聴できます。<br>• <strong>低帯域幅使用量</strong>: 制御データ (再生、一時停止、タイムスタンプ) のみが送信されるため、KoalaSync は追加の帯域幅を実質的に使用しません。 Scener はビデオ全体とカメラ フィードをクラウド サーバー経由でストリーミングします。これにより、遅いインターネット接続や古いラップトップに大きな負担がかかる可能性があります。<br>• <strong>完全に無料、広告なし</strong>: 月々の購読料、広告、トラッカーはありません。<br>• <strong>ローカル ビデオ ファイル</strong>: KoalaSync はローカルで実行されるため、自分のビデオ ファイル (MP4 など) を友達と同期して見ることもできます。ファイルをブラウザのタブにドラッグ アンド ドロップするだけです。Scener のプレーヤーはクラウドで実行されるため、これはできません。",
"ALT_SCENER_MAIN_DIFF_TITLE": "主な違い",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener は、仮想クラウド ブラウザを利用し、広告と月々のサブスクリプションによって資金を調達しているウォッチ パーティー用の<strong>商用ソーシャル ネットワーク</strong>です。 KoalaSync はブラウザのタブに直接接続できる<strong>プライバシー最優先の無料同期ユーティリティ</strong>です。音声/ビデオ チャットを Discord や Teamspeak などのアプリケーションに任せ、再生を滑らかに、プライベートに、ネイティブのオリジナル品質で維持することに完全に重点を置きます。",
"ALT_SCENER_LIMITS_TITLE": "正直な限界",
"ALT_SCENER_LIMITS_BODY": "KoalaSync は<strong>組み込みのチャットやウェブカメラのサポートを提供しません</strong>。これは純粋に同期ツールであり、選択した別の音声通話ツールが必要です。さらに、KoalaSync は現在デスクトップ専用であり、ローカル ビデオ ファイルの互換性は、ブラウザがビデオ形式とオーディオ コーデックの再生をネイティブにサポートしているかどうかによって完全に決まります。",
"ALT_SCENER_SUMMARY_TITLE": "要するに",
"ALT_SCENER_SUMMARY_BODY": "ウェブカメラチャットやソーシャル機能が組み込まれた大規模なウォッチパーティーの場合、広告やプレミアムペイウォールを気にしない限り、Scener が正しい選択です。ネイティブ プレーヤー (Netflix、Prime Video、Disney+、またはローカル ブラウザ ファイルを含む) で完全に無料、広告なし、気を散らすことのないエクスペリエンスを希望し、すでに音声通話を行っている場合は、KoalaSync がよりクリーンでパフォーマンスの高いソリューションです。",
"ALT_KOSMI_TITLE": "KoalaSync と Kosmi: Netflix パーティーに代わる選択肢として、どちらがより適していますか?",
"ALT_KOSMI_META_DESC": "KoalaSync と Kosmi の正直な比較。 Kosmi の拡張機能なしセットアップが便利な理由と、KoalaSync のネイティブ ビデオ品質が優れている理由をご覧ください。",
"ALT_KOSMI_INTRO": "KoalaSync と Kosmi はどちらも、Netflix、YouTube、その他のプラットフォームを友達と同期して視聴するための優れた方法を提供します。ただし、それらの基盤となるテクノロジーは根本的に異なります。 Kosmi は、拡張機能をインストールせずに Web ブラウザーで直接実行される仮想クラウド ブラウザーを使用します。 KoalaSync は、ローカル ビデオ プレーヤーを同期する軽量の拡張機能です。どのアプローチが最適であるかは、ビデオの品質、利便性、プライバシーに関する優先順位によって異なります。",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Kosmi がより良い選択である場合",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi は、<strong>何もインストールしたくない</strong>場合、またはタブレットやスマートフォンなどのデバイスで視聴したい場合に無敵です。 Kosmi はクラウド上で仮想ブラウザを実行するため、参加するために必要なのは単純な Web リンクだけです。さらに、Kosmi はオールインワンのハングアウト プラットフォームです。同期ストリーミングに加えて、マルチプレイヤー ゲーム (レトロな NES/SNES クラシックやポーカーなど) をプレイしたり、内蔵 Web カメラ、音声、テキスト チャットを使用したりできます。セットアップなしでソーシャル ゲーム ナイやウォッチ パーティーを開きたい場合は、Kosmi が素晴らしいソリューションです。",
"ALT_KOSMI_WHEN_KOALA_TITLE": "KoalaSync がより適切にフィットすると",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync は<strong>ネイティブ再生の品質、セキュリティ、 パフォーマンス</strong>という点で優れています。<br><br>• <strong>セキュリティ リスクなし</strong>: Kosmi を使用すると、クラウド内のリモート仮想コンピュータで Netflix または Prime アカウントにログインする必要があります。 KoalaSync を使用すると、通常と同じように、自分のブラウザで公式ストリーミング Web サイトに安全にログインできます。パスワードがマシンから流出することはありません。<br>• <strong>フル ビデオ品質 (4K/HDR)</strong>: Kosmi は仮想ブラウザの画面を圧縮ビデオ フィードとしてストリーミングするため、ピクセルやバッファリングが発生する可能性があります。 KoalaSync はネイティブ プレーヤーをローカルに同期します。サブスクリプションの鮮明なフル解像度で映画をお楽しみいただけます。<br>• <strong>遅延がなく、帯域幅に優しい</strong>: KoalaSync は制御コマンド (再生/一時停止/タイムスタンプ) のみを送信するため、帯域幅の使用はほぼゼロです。 Kosmi は常に HD ビデオ フィードをストリーミングするため、低速接続では圧倒される可能性があります。<br>• <strong>ローカル ビデオ ファイル</strong>: プライベート ビデオを見たい場合は、MP4 ファイルをブラウザ タブにドラッグ アンド ドロップして同期するだけです。 Kosmi はローカル ハード ドライブ上のファイルにアクセスできません。",
"ALT_KOSMI_MAIN_DIFF_TITLE": "主な違い",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi はリモートブラウザの画面をストリーミングする<strong>仮想クラウドハングアウト</strong>であるため、拡張機能をインストールする必要はありません。 KoalaSync は、 公式ストリーミング Web サイトのネイティブ プレーヤーに直接接続する<strong>ローカル ブラウザ同期レイヤー</strong>です。 Kosmi はミニゲームやデバイスの互換性に関してより多用途ですが、KoalaSync は元のプレーヤーでより安全で、滑らかで、鮮明なストリーミング エクスペリエンスを提供します。",
"ALT_KOSMI_LIMITS_TITLE": "正直な限界",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync は<strong>ブラウザ拡張機能をインストールする必要</strong>があり、現時点ではデスクトップ PC でのみ動作します。とにかくすでにDiscordや他の音声ツールを介して話しているという前提に基づいて設計されているため、<strong>チャットやウェブカメラは組み込まれていません</strong>。また、内蔵ゲームも提供していません。",
"ALT_KOSMI_SUMMARY_TITLE": "要するに",
"ALT_KOSMI_SUMMARY_BODY": "レトロなクラシックを楽しみながら、インストールせずにモバイルデバイスで簡単にアクセスできるカジュアルなゲームナイトには、Kosmi が最適です。最大限のセキュリティと最小限の帯域幅への影響で、Netflix、Prime Video、Disney+、または Plex でフル 4K 品質のプレミアム映画ナイトを視聴するには、KoalaSync が明らかに勝者です。",
"ALT_TWOSEVEN_TITLE": "KoalaSync と TwoSeven: どちらのウォッチ パーティー ソリューションがより適していますか?",
"ALT_TWOSEVEN_META_DESC": "KoalaSync と TwoSeven の正直な比較。 TwoSeven の内蔵 Web カメラがどのような場合に最適なのか、そして KoalaSync が Disney+ と Netflix に最適である理由をご確認ください。",
"ALT_TWOSEVEN_INTRO": "KoalaSync と TwoSeven は両方とも、ウォッチ パーティーに対して同じ基本的なアプローチを使用します。つまり、クラウドから圧縮されたビデオ フィードをストリーミングするのではなく、ブラウザーでオリジナルのビデオ プレーヤーを直接同期します。これにより、両方のツールで最高レベルのビデオ品質が保証されます。ただし、TwoSeven は Web カメラ チャットとサブスクリプション層が組み込まれた商用ポータルですが、KoalaSync は依然としてミニマリストで完全に無料でプライバシーに配慮した拡張機能です。ここであなたに最適なサービスを見つけてください。",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "TwoSeven がより良い選択である場合",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "ブラウザに直接統合されたウェブカメラと音声チャット</strong>を備えた<strong>オールインワン ソリューションが必要な場合は、TwoSeven が正しい選択です。バックグラウンドで Discord や Teamspeak を実行せずに視聴中に友達を見たい場合は、TwoSeven がこの統合をネイティブに提供します。さらに、YouTube および拡張機能なしのいくつかのオープン Web ビデオ プレーヤーでも機能します。視聴中に視覚的なつながりを共有したい 2 ~ 3 人の小グループに適しています。",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "KoalaSync がより適切にフィットすると",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync は<strong>手数料、プライバシー、 シンプルさの完全な欠如</strong>で優れています:<br><br>• <strong>ペイウォールなし</strong>: Disney+ や Hulu などのプレミアム サービスを TwoSeven で同期して視聴するには、少なくとも 1 人のルーム メンバーが Patreon でサービスをサポートする必要があります (月額 3 ドルから)。 KoalaSync は、Netflix、Prime Video、Disney+、自己ホスト型メディア サーバー (Jellyfin、Plex、Emby) を 100% 無料で制限なしで同期します。<br>• <strong>絶対プライバシー (トラッカー/広告なし)</strong>: TwoSeven は広告でサポートされており、Google、Facebook などの複数のトラッカーを使用しています。 KoalaSync には広告やトラッカーがなく、RAM のみのリレー サーバーとのみ通信します。<br>• <strong>登録は不要</strong>: TwoSeven では、すべての参加者がアカウントを作成してログインする必要があります。KoalaSync は完全にアカウント不要です。インストールしてルームコードを入力するだけで、視聴を開始できます。<br>• <strong>軽量でリソースに優しい</strong>: TwoSeven の統合されたウェブカメラとオーディオ フィードは、CPU とネットワークに大きな負荷をかけます。 Discord などのツールに通信を任せることで、KoalaSync は非常にスムーズに動作し、バッテリー寿命を節約できます。",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "主な違い",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven は、登録要件、広告、ピアツーピア Web カメラ チャット、および特定のストリーミング サービス用の Patreon ペイウォールを備えた<strong>商用プラットフォーム</strong>です。 KoalaSync は<strong>無料のオープンソース ユーティリティ</strong>で、アカウントやトラッカー、追加費用なしでブラウザのタブに直接接続できるため、ネイティブ プレーヤーで気を散らすことなく視聴できます。",
"ALT_TWOSEVEN_LIMITS_TITLE": "正直な限界",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync は<strong>内蔵ウェブカメラや音声チャットを提供していません</strong>ので、Discord または同様のツールを介してすでに通話中であることを前提としています。さらに、KoalaSync にはチャット ボックス オーバーレイが組み込まれておらず、現時点ではデスクトップのみです。",
"ALT_TWOSEVEN_SUMMARY_TITLE": "要するに",
"ALT_TWOSEVEN_SUMMARY_BODY": "ブラウザのウェブカメラを介して直接お互いに会いたい、Disney+ サポートのために Patreon をサポートすることを気にしない 2 人または 3 人の小グループにとって、TwoSeven は良い選択肢です。登録なしで広告なし、完全無料、ネイティブ 4K 品質 (Netflix、Prime Video、Disney+、Jellyfin のいずれでも) でプライベートな映画鑑賞をするには、KoalaSync がよりクリーンで安全な選択肢です。",
"ALT_TRY_KOALASYNC": "KoalaSyncを試す",
"MOCK_HOST_CONTROL_LABEL": "ホスト操作",
"MOCK_HOST_CONTROL_TOGGLE": "自分だけが再生を操作できる",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync는 음성 통화를 대체하는 서비스가 아닙니다. 영상을 보면서 대화하고 싶다면 평소처럼 Discord, Teamspeak, Signal, WhatsApp 등을 그대로 사용하면 됩니다.<br><br>또한 모든 참가자가 각자의 기기에서 해당 영상이나 페이지에 접속할 수 있어야 합니다. KoalaSync는 구독, 로그인, DRM, 지역 제한 또는 플랫폼 규정을 우회하지 않습니다.<br><br>현재 데스크톱 브라우저에서만 지원되며, 자체 채팅이나 음성 기능은 없습니다. 호환성은 항상 브라우저 및 동영상 플레이어의 영향을 받습니다.",
"ALT_SCREEN_SUMMARY_TITLE": "요약",
"ALT_SCREEN_SUMMARY_BODY": "화질, 개인정보 보호, 개별 제어 기능 등을 크게 신경 쓰지 않고 간편하게 진행하고 싶을 때는 화면 공유가 가장 간단한 방법입니다. 반면, 모든 참가자가 각자의 브라우저에서 직접 영상을 시청하며 실제로 함께 보는 듯한 느낌을 원한다면 KoalaSync가 더 적합합니다.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync Watch2Gether: 어떤 시계 파티 솔루션이 더 적합합니까?",
"ALT_W2G_META_DESC": "KoalaSync Watch2Gether의 솔직한 비교입니다. KoalaSync의 유연성이 탁월한 이유와 Watch2Gether가 여전히 YouTube에서 최고의 선택인 이유를 알아보세요.",
"ALT_W2G_INTRO": "KoalaSync Watch2Gether는 모두 동일한 문제를 해결합니다. 수동으로 조정하지 않고도 온라인으로 친구들과 동기화된 비디오를 볼 수 있습니다. Watch2Gether는 공유 영화의 밤을 위한 가장 오래되고 가장 인기 있는 허브 중 하나이지만 KoalaSync는 완전히 다른 가벼운 접근 방식을 취합니다. 귀하에게 적합한 도구는 무엇을, 어디서 보고 싶은지에 따라 크게 달라집니다.",
"ALT_W2G_WHEN_W2G_TITLE": "Watch2Gether가 더 나은 선택인 경우",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether는 <strong>YouTube 시청 파티</strong>에서 최고의 앱입니다. 내장된 재생 목록 및 검색 기능을 통해 회의실에 있는 누구나 쉽게 새 비디오를 찾고, 추가하고, 재생할 수 있습니다. 모두가 함께 원활하게 다음 동영상을 시청합니다.<br><br>YouTube의 KoalaSync를 사용하면 사이트의 기본 자동 재생이 대신되어 각 사용자를 다른 추천 동영상으로 리디렉션합니다. Netflix 또는 Disney+에서 잘 작동하는 자동 다음 에피소드 기능('에피소드 로비')은 이러한 동적 추천으로 인해 YouTube에서는 작동하지 않습니다. 순수한 YouTube 밤에는 Watch2Gether가 더 나은 선택입니다.",
"ALT_W2G_WHEN_KOALA_TITLE": "KoalaSync가 더 잘 맞을 때",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync는 <strong>실제 스트리밍 서비스</strong>(Netflix, Prime Video, Disney+) 및 자체 호스팅 미디어 서버(Jellyfin, Plex, Emby)에서 빛을 발합니다. 프리미엄 콘텐츠를 전혀 재생할 수 없는 Watch2Gether와 달리 KoalaSync는 웹사이트에서 직접 기본 플레이어를 동기화합니다.<br><br>표준 HTML5 비디오 플레이어가 있는 거의 모든 사이트에서 작동합니다. 타사 사이트에 가상 방을 설정할 필요가 없습니다. 확장 프로그램을 활성화하고 로비에 참여하고 시청을 시작하기만 하면 됩니다.",
"ALT_W2G_MAIN_DIFF_TITLE": "주요 차이점",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether는 채팅, 재생목록, 웹캠 지원 기능이 내장된 <strong>독립형 웹사이트</strong>입니다. KoalaSync는 일반 브라우저 탭에 직접 연결되는 <strong>미니멀리스트 브라우저 확장 프로그램</strong>입니다.<br><br>채팅 기능이 내장된 YouTube용 올인원 패키지를 찾고 계십니까? Watch2Gether를 사용하세요. 방해받지 않고 기본 품질(서버 압축 없음)로 Netflix 또는 자체 서버에서 영화를 시청하고 싶으십니까? KoalaSync는 더욱 깨끗한 솔루션입니다.",
"ALT_W2G_LIMITS_TITLE": "정직한 제한",
"ALT_W2G_LIMITS_BODY": "KoalaSync에는 <strong>재생목록이나 동영상 검색 기능이 내장되어 있지 않습니다</strong>. YouTube에서 이는 다음 동영상의 자동 재생이 동기화되지 않음을 의미합니다.<br><br>또한 <strong>내장된 채팅이 없으며</strong> KoalaSync는 현재 데스크톱 브라우저에서만 작동합니다. 어쨌든 Discord, Teamspeak 또는 기타 음성 도구를 통해 이미 대화하고 있다는 가정하에 설계되었습니다.",
"ALT_W2G_SUMMARY_TITLE": "요컨대",
"ALT_W2G_SUMMARY_BODY": "재생 목록과 내장된 채팅이 포함된 즉석 YouTube 세션의 경우 Watch2Gether가 최선의 선택입니다. 프리미엄 스트리밍 플랫폼(예: Netflix, Prime Video, Disney+), 자체 호스팅 서버(Jellyfin, Plex, Emby) 및 최대 브라우저 유연성의 경우 KoalaSync가 더 적합하고 가벼운 도구입니다.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: 어떤 시계 파티 플랫폼이 더 잘 맞나요?",
"ALT_SCENER_META_DESC": "KoalaSync와 Scener를 정직하게 비교합니다. Scener의 웹캠 채팅이 언제 승리하는지, 왜 KoalaSync가 방해 없는 영화 감상에 가장 적합한지 알아보세요.",
"ALT_SCENER_INTRO": "KoalaSync와 Scener는 완전히 다른 두 가지 각도에서 시계 파티에 접근합니다. Scener는 영상 채팅과 대화형 룸이 내장된 가상 영화관입니다. 반면에 KoalaSync는 재생 컨트롤을 간단히 동기화하는 미니멀하고 개인 정보 보호 친화적인 브라우저 확장 프로그램입니다. 귀하에게 가장 적합한 도구는 기본적으로 내장된 웹캠과 채팅 기능이 귀하에게 얼마나 중요한지에 따라 달라집니다.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Scener가 더 나은 선택일 때",
"ALT_SCENER_WHEN_SCENER_BODY": "브라우저에 직접 영상 및 음성 채팅이 내장된 <strong>올인원 소셜 플랫폼</strong>을 원하는 경우 Scener는 확실한 선택입니다. Scener는 플레이어와 친구의 웹캠이 나란히 표시되는 가상 공간을 만듭니다. 이는 사회적 측면이 최우선인 대규모 공개 시청 파티 또는 가상 스트리밍 이벤트에 이상적입니다. 그러나 무료 기본 버전은 광고가 지원되며 Scener는 월간 구독($5.79/월 또는 $39.99/년) 뒤에 많은 기능(예: 광고 없는 시청 및 무제한 화상 채팅)을 고정한다는 점을 명심하세요.",
"ALT_SCENER_WHEN_KOALA_TITLE": "KoalaSync가 더 잘 맞을 때",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync는 <strong>동영상 품질, 개인 정보 보호 및 단순성</strong> 면에서 빛을 발합니다.<br><br>• <strong>계정 없음</strong>: 등록, 로그인 또는 프로필 관리가 필요하지 않습니다. 확장 프로그램을 활성화하고 방 코드를 공유하고 시청을 시작하세요.<br>• <strong>진정한 기본 품질(4K/HDR)</strong>: Scener는 가상 클라우드 서버에서 압축된 비디오를 스트리밍하므로 품질 손실과 지연이 발생할 수 있습니다. KoalaSync는 컴퓨터에서 기본 플레이어를 직접 동기화합니다. 즉, 스트리밍 구독의 전체 해상도로 영화를 감상할 수 있습니다.<br>• <strong>은 대역폭 사용량</strong>: 제어 데이터(재생, 일시중지, 타임스탬프)만 전송되므로 KoalaSync는 사실상 추가 대역폭을 사용하지 않습니다. Scener는 클라우드 서버를 통해 전체 동영상과 카메라 피드를 스트리밍하므로 느린 인터넷 연결과 구형 노트북에 큰 부담을 줄 수 있습니다.<br>• <strong>100% 무료이고 광고가 없습니다</strong>: 월간 구독료가 없고, 광고가 없으며, 추적기도 없습니다.<br>• <strong>로컬 동영상 파일</strong>: KoalaSync는 로컬에서 실행되므로 친구와 동기화하여 자신의 동영상 파일(예: MP4)을 볼 수도 있습니다. 파일을 브라우저 탭으로 끌어다 놓기만 하면 됩니다. Scener는 플레이어가 클라우드에서 실행되기 때문에 이 작업을 수행할 수 없습니다.",
"ALT_SCENER_MAIN_DIFF_TITLE": "주요 차이점",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener는 가상 클라우드 브라우저로 구동되고 광고와 월간 구독을 통해 자금을 조달하는 시청 파티를 위한 <strong>상업적 소셜 네트워크</strong>입니다. KoalaSync는 브라우저 탭에 직접 연결되는 <strong>개인 정보 보호를 최우선으로 하는 무료 동기화 유틸리티</strong>입니다. 음성/영상 채팅은 Discord 또는 Teamspeak와 같은 애플리케이션에 맡기고 재생을 유연하고 비공개이며 기본 원본 품질로 유지하는 데 전적으로 중점을 둡니다.",
"ALT_SCENER_LIMITS_TITLE": "정직한 제한",
"ALT_SCENER_LIMITS_BODY": "KoalaSync는 <strong>채팅이나 웹캠 지원 기능이 내장되어 있지 않습니다</strong>. 이는 순전히 동기화 도구이며 선택한 별도의 음성 통화 도구가 필요합니다. 또한 KoalaSync는 현재 데스크톱 전용이며 로컬 비디오 파일 호환성은 브라우저가 기본적으로 비디오 형식 및 오디오 코덱 재생을 지원하는지 여부에 따라 전적으로 달라집니다.",
"ALT_SCENER_SUMMARY_TITLE": "요컨대",
"ALT_SCENER_SUMMARY_BODY": "웹캠 채팅과 소셜 기능이 내장된 대규모 시청 파티의 경우 광고와 프리미엄 페이월에 신경 쓰지 않는다면 Scener가 올바른 선택입니다. 기본 플레이어(Netflix, Prime Video, Disney+ 또는 로컬 브라우저 파일 포함)에서 완전히 무료이고, 광고가 없고, 방해 없는 경험을 원하고 이미 음성 통화 중이라면 KoalaSync가 더 깔끔하고 성능이 뛰어난 솔루션입니다.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: 어떤 Netflix 파티 대안이 더 잘 맞나요?",
"ALT_KOSMI_META_DESC": "KoalaSync와 Kosmi의 솔직한 비교입니다. Kosmi의 확장 없는 설정이 편리한 이유와 KoalaSync의 기본 비디오 품질이 뛰어난 이유를 알아보세요.",
"ALT_KOSMI_INTRO": "KoalaSync와 Kosmi는 모두 친구들과 동기화하여 Netflix, YouTube 및 기타 플랫폼을 시청할 수 있는 훌륭한 방법을 제공합니다. 그러나 기본 기술은 근본적으로 다릅니다. 코스미는 확장 프로그램 설치 없이 웹 브라우저에서 직접 실행되는 가상 클라우드 브라우저를 사용합니다. KoalaSync는 로컬 비디오 플레이어를 동기화하는 경량 확장 프로그램입니다. 귀하에게 가장 적합한 접근 방식은 비디오 품질, 편의성 및 개인정보 보호에 대한 우선순위에 따라 다릅니다.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "코스미가 더 나은 선택일 때",
"ALT_KOSMI_WHEN_KOSMI_BODY": "<strong>아무 것도 설치하지 않고</strong> 태블릿이나 스마트폰과 같은 기기에서 시청하고 싶다면 Kosmi는 최고의 앱입니다. 코스미는 클라우드에서 가상 브라우저를 실행하기 때문에 간단한 웹 링크만 있으면 가입할 수 있습니다. 또한 Kosmi는 올인원 행아웃 플랫폼입니다. 동기화된 스트리밍 외에도 멀티플레이어 게임(예: 레트로 NES/SNES 클래식 또는 포커)을 플레이하고 내장 웹캠, 음성 및 문자 채팅을 사용할 수 있습니다. 설정 없이 소셜 게임의 밤과 파티 시청을 원한다면 Kosmi가 환상적인 솔루션입니다.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "KoalaSync가 더 잘 맞을 때",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync는 <strong>기본 재생 품질, 보안 및 성능</strong>에서 빛을 발합니다.<br><br>• <strong>보안 위험 없음</strong>: Kosmi를 사용하면 클라우드의 원격 가상 컴퓨터에서 Netflix 또는 Prime 계정에 로그인해야 합니다. KoalaSync를 사용하면 평소와 마찬가지로 자신의 브라우저에서 공식 스트리밍 웹사이트에 안전하게 로그인할 수 있습니다. 비밀번호는 컴퓨터 외부로 유출되지 않습니다.<br>• <strong>전체 동영상 품질(4K/HDR)</strong>: Kosmi는 가상 브라우저의 화면을 압축된 동영상 피드로 스트리밍하므로 픽셀화 및 버퍼링이 발생할 수 있습니다. KoalaSync는 기본 플레이어를 로컬로 동기화합니다. 구독의 완전하고 선명한 해상도로 영화를 즐길 수 있습니다.<br>• <strong>지연이 없고 대역폭 친화적</strong>: KoalaSync는 제어 명령(재생/일시 중지/타임스탬프)만 보내기 때문에 거의 0의 대역폭을 사용합니다. Kosmi는 지속적으로 HD 동영상 피드를 스트리밍하므로 연결 속도가 느려질 수 있습니다.<br>• <strong>로컬 동영상 파일</strong>: 비공개 동영상을 시청하려면 MP4 파일을 브라우저 탭으로 드래그 앤 드롭하고 동기화하면 됩니다. Kosmi는 로컬 하드 드라이브의 파일에 접근할 수 없습니다.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "주요 차이점",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi는 원격 브라우저의 화면을 스트리밍하는 <strong>가상 클라우드 행아웃</strong>이므로 누구도 확장 프로그램을 설치할 필요가 없습니다. KoalaSync는 공식 스트리밍 웹사이트의 기본 플레이어에 직접 연결되는 <strong>로컬 브라우저 동기화 레이어</strong>입니다. Kosmi는 미니 게임 및 장치 호환성 측면에서 더 다재다능한 반면 KoalaSync는 원래 플레이어에서 더 안전하고 유연하며 선명한 스트리밍 경험을 제공합니다.",
"ALT_KOSMI_LIMITS_TITLE": "정직한 제한",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync는 <strong>브라우저 확장 프로그램을 설치해야 하며</strong> 현재 데스크톱 PC에서만 실행됩니다. 어쨌든 Discord나 다른 음성 도구를 통해 이미 대화하고 있다는 가정하에 설계되었기 때문에 <strong>내장 채팅이나 웹캠이 없습니다</strong>. 또한 내장 게임도 제공하지 않습니다.",
"ALT_KOSMI_SUMMARY_TITLE": "요컨대",
"ALT_KOSMI_SUMMARY_BODY": "설치 없이 모바일 장치에서 쉽게 액세스할 수 있고 레트로 클래식을 즐길 수 있는 캐주얼한 게임 밤에는 Kosmi가 이상적입니다. 최대의 보안과 최소의 대역폭 영향으로 Netflix, Prime Video, Disney+ 또는 Plex에서 풀 4K 품질로 프리미엄 영화를 감상하는 경우 KoalaSync가 확실한 승자입니다.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: 어떤 시계 파티 솔루션이 더 적합할까요?",
"ALT_TWOSEVEN_META_DESC": "KoalaSync와 TwoSeven의 솔직한 비교입니다. TwoSeven의 내장 웹캠이 성공하는 시기와 KoalaSync가 Disney+ 및 Netflix에 가장 적합한 이유를 알아보세요.",
"ALT_TWOSEVEN_INTRO": "KoalaSync와 TwoSeven은 모두 함께 시청하기 위해 동일한 기본 접근 방식을 사용합니다. 즉, 클라우드에서 압축된 비디오 피드를 스트리밍하는 대신 브라우저에서 직접 원본 비디오 플레이어를 동기화합니다. 이는 두 도구 모두에 대해 최고 수준의 비디오 품질을 보장합니다. 그러나 TwoSeven은 웹캠 채팅 및 구독 계층이 내장된 상업용 포털인 반면 KoalaSync는 최소한의 완전 무료이며 개인 정보 보호 친화적인 확장 기능을 유지합니다. 여기에서 귀하에게 가장 적합한 서비스를 찾아보세요.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "TwoSeven이 더 나은 선택일 때",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "브라우저에서 직접 <strong>웹캠과 오디오 채팅이 통합된 올인원 솔루션</strong>을 원하는 경우 TwoSeven이 올바른 선택입니다. 백그라운드에서 Discord나 Teamspeak를 실행할 필요 없이 시청하는 동안 친구들을 보고 싶다면 TwoSeven이 이 통합 기능을 기본적으로 제공합니다. 또한 확장 기능이 없는 YouTube 및 일부 개방형 웹 비디오 플레이어에서도 작동합니다. 시청하면서 시각적 연결을 공유하려는 2~3명의 소규모 그룹에 적합합니다.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "KoalaSync가 더 잘 맞을 때",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync는 <strong>수수료, 개인 정보 보호 및 단순성이 전혀 없음</strong>으로 빛을 발합니다.<br><br>• <strong>페이월 없음</strong>: TwoSeven에서 Disney+ 또는 Hulu와 같은 프리미엄 서비스를 동기화하려면 최소 한 명의 룸 멤버가 Patreon에서 지원해야 합니다(월 3달러부터 시작). KoalaSync는 Netflix, Prime Video, Disney+ 및 자체 호스팅 미디어 서버(Jellyfin, Plex, Emby)를 제한 없이 100% 무료로 동기화합니다.<br>• <strong>추적기/광고 없음</strong>: TwoSeven은 광고가 지원되며 Google, Facebook 등의 여러 추적기를 사용합니다. KoalaSync에는 광고나 추적기가 없으며 RAM 전용 릴레이 서버와 독점적으로 통신합니다.<br>• <strong>등록이 필요하지 않습니다</strong>: TwoSeven은 모든 참가자에게 계정을 만들고 로그인하도록 요구합니다. KoalaSync는 계정이 전혀 필요하지 않습니다. 설치하고 방 코드를 입력하고 시청을 시작하세요.<br>• <strong>경량 및 리소스 친화적</strong>: TwoSeven의 통합 웹캠과 오디오 피드는 CPU와 네트워크에 큰 부하를 줍니다. Discord와 같은 도구와의 통신을 유지함으로써 KoalaSync는 매우 원활하게 실행되고 배터리 수명을 보존니다.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "주요 차이점",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven은 등록 요구 사항, 광고, P2P 웹캠 채팅, 특정 스트리밍 서비스에 대한 Patreon 페이월을 갖춘 <strong>상업 플랫폼</strong>입니다. KoalaSync는 계정, 추적기 또는 추가 비용 없이 브라우저 탭에 직접 연결되는 <strong>무료 오픈 소스 유틸리티</strong>로, 기본 플레이어에서 방해 없이 시청할 수 있습니다.",
"ALT_TWOSEVEN_LIMITS_TITLE": "정직한 제한",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync는 <strong>내장 웹캠이나 오디오 채팅이 없으며</strong> Discord 또는 유사한 도구를 통해 이미 통화 중이라고 가정합니다. 또한 KoalaSync에는 채팅 상자 오버레이가 내장되어 있지 않으며 현재 데스크톱 전용입니다.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "요컨대",
"ALT_TWOSEVEN_SUMMARY_BODY": "브라우저에서 직접 웹캠을 통해 서로를 보고 싶어하고 Patreon에서 Disney+ 지원을 지원하는 것을 꺼리지 않는 2~3명으로 구성된 소규모 그룹의 경우 TwoSeven이 좋은 옵션입니다. 등록 없이 네이티브 4K 품질(Netflix, Prime Video, Disney+, Jellyfin 등)로 광고 없이 완전 무료로 비공개 영화를 감상하려면 KoalaSync가 더 깨끗하고 안전한 선택입니다.",
"ALT_TRY_KOALASYNC": "KoalaSync 사용해 보기",
"MOCK_HOST_CONTROL_LABEL": "호스트 제어",
"MOCK_HOST_CONTROL_TOGGLE": "나만 재생을 제어할 수 있음",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync is geen vervanging voor een spraakgesprek. Als je tijdens het kijken wilt praten, gebruik je gewoon Discord, Teamspeak, Signal, WhatsApp of wat je normaal ook gebruikt.<br><br>Iedereen heeft ook toegang tot de video of pagina op het eigen apparaat nodig. KoalaSync omzeilt geen abonnementen, inloggegevens, DRM, regionale beperkingen of platformregels.<br><br>Het werkt momenteel alleen in desktopbrowsers, heeft geen ingebouwde chat- of spraakfunctie en de compatibiliteit hangt altijd af van de browser en de videospeler.",
"ALT_SCREEN_SUMMARY_TITLE": "Samenvatting",
"ALT_SCREEN_SUMMARY_BODY": "Scherm delen is de eenvoudigste optie als je snel iets wilt doen en niet veel waarde hecht aan kwaliteit, privacy of individuele controle. KoalaSync is een betere keuze wanneer iedereen lokaal in de eigen browser moet kijken en de sessie meer moet aanvoelen als echt samen kijken.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: welke watchparty-oplossing past beter?",
"ALT_W2G_META_DESC": "Een eerlijke vergelijking tussen KoalaSync en Watch2Gether. Ontdek wanneer de flexibiliteit van KoalaSync onverslaanbaar is en waarom Watch2Gether nog steeds de beste keuze is voor YouTube.",
"ALT_W2G_INTRO": "KoalaSync en Watch2Gether lossen beide hetzelfde probleem op: online video's online bekijken met vrienden zonder handmatig te coördineren. Hoewel Watch2Gether een van de oudste en meest populaire hubs is voor gedeelde filmavonden, hanteert KoalaSync een compleet andere, lichtgewicht aanpak. Welke tool voor jou geschikt is, hangt sterk af van wat en waar je wilt kijken.",
"ALT_W2G_WHEN_W2G_TITLE": "Wanneer Watch2Gether de betere keuze is",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is onverslaanbaar voor <strong>YouTube-kijkfeesten</strong>. Dankzij de ingebouwde afspeellijst en zoekfunctie kan iedereen in de kamer eenvoudig nieuwe video's vinden, toevoegen en afspelen. Iedereen kijkt naadloos samen naar de volgende video.<br><br>Met KoalaSync op YouTube neemt de standaard autoplay van de site het over, waardoor elke gebruiker wordt omgeleid naar een andere aanbevolen video. Onze automatische functie voor volgende afleveringen (\"Episode Lobby\"), die prima werkt op Netflix of Disney+, werkt niet op YouTube vanwege deze dynamische aanbevelingen. Voor pure YouTube-avonden is Watch2Gether de betere keuze.",
"ALT_W2G_WHEN_KOALA_TITLE": "Wanneer KoalaSync beter past",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync schittert op <strong>echte streamingdiensten</strong> (Netflix, Prime Video, Disney+) en zelfgehoste mediaservers (Jellyfin, Plex, Emby). In tegenstelling tot Watch2Gether, dat vaak helemaal geen premium-inhoud kan afspelen, synchroniseert KoalaSync de native speler rechtstreeks op de website.<br><br>Het werkt op vrijwel elke site met een standaard HTML5-videospeler. U hoeft geen virtuele kamer op te zetten op een site van derden: activeer gewoon de extensie, sluit u aan bij een lobby en begin met kijken.",
"ALT_W2G_MAIN_DIFF_TITLE": "Het belangrijkste verschil",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is een <strong>zelfstandige website</strong> met ingebouwde chat, afspeellijsten en webcamondersteuning. KoalaSync is een <strong>minimalistische browserextensie</strong> die rechtstreeks aansluit op je normale browsertabbladen.<br><br>Op zoek naar een alles-in-één pakket voor YouTube met ingebouwde chat? Gebruik Watch2Gether. Wil je films kijken op Netflix of je eigen server zonder afleiding, in native kwaliteit (geen servercompressie)? KoalaSync is de schonere oplossing.",
"ALT_W2G_LIMITS_TITLE": "Eerlijke beperkingen",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>heeft geen ingebouwde afspeellijsten of videozoekfunctie</strong>. Op YouTube betekent dit dat het automatisch afspelen van de volgende video niet gesynchroniseerd blijft.<br><br>Bovendien is er <strong>geen ingebouwde chat</strong> en werkt KoalaSync momenteel alleen in desktopbrowsers. Het is ontworpen in de veronderstelling dat je sowieso al via Discord, Teamspeak of andere spraaktools praat.",
"ALT_W2G_SUMMARY_TITLE": "Kortom",
"ALT_W2G_SUMMARY_BODY": "Voor spontane YouTube-sessies met afspeellijsten en ingebouwde chat is Watch2Gether de beste keuze. Voor premium streamingplatforms (zoals Netflix, Prime Video, Disney+), zelfgehoste servers (Jellyfin, Plex, Emby) en maximale browserflexibiliteit is KoalaSync de geschiktere en lichtgewicht tool.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: welk watchparty-platform past beter?",
"ALT_SCENER_META_DESC": "Een eerlijke vergelijking van KoalaSync en Scener. Ontdek wanneer de webcamchat van Scener wint en waarom KoalaSync het beste is voor filmavonden zonder afleiding.",
"ALT_SCENER_INTRO": "KoalaSync en Scener benaderen feestjes vanuit twee totaal verschillende invalshoeken. Scener is een virtuele bioscoop met ingebouwde videochat en interactieve kamers. KoalaSync daarentegen is een minimalistische, privacyvriendelijke browserextensie die eenvoudig de afspeelbedieningen synchroniseert. Welke tool het beste bij u past, hangt vooral af van hoe belangrijk ingebouwde webcam- en chatfuncties voor u zijn.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Wanneer Scener de betere keuze is",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener is een solide keuze als je een <strong>alles-in-één sociaal platform</strong> met ingebouwde video- en audiochat rechtstreeks in je browser wilt. Scener creëert een virtuele kamer waar de webcams van de speler en je vrienden naast elkaar worden weergegeven. Dit is ideaal voor grote, openbare kijkfeesten of virtuele streamingevenementen waarbij het sociale aspect centraal staat. Houd er echter rekening mee dat de gratis basisversie door advertenties wordt ondersteund en dat Scener veel functies (zoals advertentievrij kijken en onbeperkt videochatten) vergrendelt achter een maandelijks abonnement ($ 5,79/maand of $ 39,99/jaar).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Wanneer KoalaSync beter past",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync schittert als het gaat om <strong>videokwaliteit, privacy en eenvoud</strong>:<br><br>• <strong>Geen accounts</strong>: u hoeft zich niet te registreren, in te loggen of profielen te beheren. Activeer gewoon de extensie, deel een kamercode en begin met kijken.<br>• <strong>Echte native kwaliteit (4K/HDR)</strong>: Scener streamt gecomprimeerde video vanaf een virtuele cloudserver, wat kan leiden tot kwaliteitsverlies en vertraging. KoalaSync synchroniseert de native speler rechtstreeks op uw computer, wat betekent dat u films bekijkt in de volledige resolutie van uw streamingabonnement.<br>• <strong>Laag bandbreedtegebruik</strong>: Omdat alleen besturingsgegevens (afspelen, pauzeren, tijdstempels) worden verzonden, gebruikt KoalaSync vrijwel geen extra bandbreedte. Scener streamt de volledige video- en camerafeeds via cloudservers, wat tragere internetverbindingen en oudere laptops zwaar kan belasten.<br>• <strong>100% gratis en advertentievrij</strong>: geen maandelijkse abonnementskosten, geen advertenties en geen trackers.<br>• <strong>Lokale videobestanden</strong>: aangezien KoalaSync lokaal draait, kun je zelfs je eigen videobestanden (zoals MP4) bekijken, gesynchroniseerd met vrienden. Sleep het bestand gewoon naar een browsertabblad. Scener kan dit niet doen omdat de speler in de cloud draait.",
"ALT_SCENER_MAIN_DIFF_TITLE": "Het belangrijkste verschil",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener is een <strong>commercieel sociaal netwerk</strong> voor kijkfeesten dat wordt aangedreven door virtuele cloudbrowsers en wordt gefinancierd via advertenties en maandelijkse abonnementen. KoalaSync is een <strong>privacy-first, gratis synchronisatiehulpprogramma</strong> dat rechtstreeks op uw browsertabbladen aansluit. Het laat spraak-/videochat over aan applicaties zoals Discord of Teamspeak, waarbij de nadruk volledig ligt op het vloeiend, privé en in de oorspronkelijke originele kwaliteit houden van het afspelen.",
"ALT_SCENER_LIMITS_TITLE": "Eerlijke beperkingen",
"ALT_SCENER_LIMITS_BODY": "KoalaSync biedt <strong>geen ingebouwde chat- of webcamondersteuning</strong>. Het is puur een synchronisatietool en vereist een afzonderlijk hulpmiddel voor spraakoproepen naar keuze. Bovendien is KoalaSync momenteel alleen beschikbaar voor desktops, en de compatibiliteit van lokale videobestanden hangt volledig af van de vraag of uw browser het afspelen van het videoformaat en de audiocodecs standaard ondersteunt.",
"ALT_SCENER_SUMMARY_TITLE": "Kortom",
"ALT_SCENER_SUMMARY_BODY": "Voor grote kijkfeesten met ingebouwde webcamchat en sociale functies is Scener de juiste keuze, op voorwaarde dat je advertenties en premium betaalmuren niet erg vindt. Als je een volledig gratis, advertentievrije en afleidingsvrije ervaring wilt in de native speler (inclusief Netflix, Prime Video, Disney+ of lokale browserbestanden) en je bent al bezig met een telefoongesprek, dan is KoalaSync de schonere en beter presterende oplossing.",
"ALT_KOSMI_TITLE": "KoalaSync versus Kosmi: welk Netflix-feestalternatief past beter?",
"ALT_KOSMI_META_DESC": "Een eerlijke vergelijking van KoalaSync en Kosmi. Ontdek waarom Kosmi's configuratie zonder extensie handig is en wanneer de native videokwaliteit van KoalaSync wint.",
"ALT_KOSMI_INTRO": "Zowel KoalaSync als Kosmi bieden geweldige manieren om Netflix, YouTube en andere platforms gesynchroniseerd met vrienden te bekijken. Hun onderliggende technologieën zijn echter fundamenteel verschillend. Kosmi maakt gebruik van virtuele cloudbrowsers die rechtstreeks in uw webbrowser worden uitgevoerd zonder extensies te installeren. KoalaSync is een lichtgewicht extensie die uw lokale videospeler synchroniseert. Welke aanpak het beste bij u past, hangt af van uw prioriteiten op het gebied van videokwaliteit, gemak en privacy.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Wanneer Kosmi de betere keuze is",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi is onverslaanbaar als je <strong>niets wilt installeren</strong> of wilt kijken op apparaten zoals tablets en smartphones. Omdat Kosmi virtuele browsers in de cloud draait, is het enige dat nodig is om deel te nemen een eenvoudige weblink. Bovendien is Kosmi een alles-in-één hangoutplatform: naast gesynchroniseerde streaming kun je multiplayer-spellen spelen (zoals retro NES/SNES-klassiekers of poker) en de ingebouwde webcam, stem- en tekstchat gebruiken. Als je een sociale game-avond wilt en een feestje wilt kijken zonder opstelling, is Kosmi een fantastische oplossing.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Wanneer KoalaSync beter past",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync blinkt uit als het gaat om <strong>native afspeelkwaliteit, beveiliging en prestaties</strong>:<br><br>• <strong>Geen beveiligingsrisico's</strong>: met Kosmi moet je inloggen op je Netflix- of Prime-account op een externe virtuele computer in de cloud. Met KoalaSync log je veilig in op de officiële streamingwebsite in je eigen browser, net zoals je normaal doet. Je wachtwoorden verlaten je machine nooit.<br>• <strong>Volledige videokwaliteit (4K/HDR)</strong>: Kosmi streamt het scherm van de virtuele browser als een gecomprimeerde videofeed, wat kan resulteren in pixelvorming en buffering. KoalaSync synchroniseert de native spelers lokaal: je geniet van films in de volledige, kristalheldere resolutie van je abonnement.<br>• <strong>Lag-vrij en bandbreedtevriendelijk</strong>: omdat KoalaSync alleen besturingsopdrachten verzendt (afspelen/pauzeren/tijdstempels), gebruikt het bijna geen bandbreedte. Kosmi streamt voortdurend HD-videofeeds, waardoor langzamere verbindingen kunnen worden overweldigd.<br>• <strong>Lokale videobestanden</strong>: als je een privévideo wilt bekijken, sleep je het MP4-bestand gewoon naar een browsertabblad en synchroniseer je het. Kosmi heeft geen toegang tot bestanden op uw lokale harde schijf.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "Het belangrijkste verschil",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi is een <strong>virtuele cloud-hangout</strong> die het scherm van een externe browser streamt, zodat niemand een extensie hoeft te installeren. KoalaSync is een <strong>lokale browsersynchronisatielaag</strong> die rechtstreeks aansluit op de native speler op de officiële streamingwebsite. Hoewel Kosmi veelzijdiger is op het gebied van minigames en apparaatcompatibiliteit, biedt KoalaSync een veiligere, vloeiendere en scherpere streamingervaring in de originele speler.",
"ALT_KOSMI_LIMITS_TITLE": "Eerlijke beperkingen",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>vereist de installatie van een browserextensie</strong> en werkt momenteel alleen op desktop-pc's. Het <strong>heeft geen ingebouwde chat of webcams</strong>, omdat het is ontworpen in de veronderstelling dat je toch al via Discord of andere stemhulpmiddelen praat. Het biedt ook geen ingebouwde games.",
"ALT_KOSMI_SUMMARY_TITLE": "Kortom",
"ALT_KOSMI_SUMMARY_BODY": "Voor informele game-avonden met retro-klassiekers en gemakkelijke toegang op mobiele apparaten zonder enige installatie is Kosmi ideaal. Voor premium filmavonden op Netflix, Prime Video, Disney+ of Plex in volledige 4K-kwaliteit, met maximale beveiliging en minimale impact op de bandbreedte, is KoalaSync de duidelijke winnaar.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: welke watchparty-oplossing past beter?",
"ALT_TWOSEVEN_META_DESC": "Een eerlijke vergelijking van KoalaSync en TwoSeven. Ontdek wanneer de ingebouwde webcam van TwoSeven wint en waarom KoalaSync het beste is voor Disney+ en Netflix.",
"ALT_TWOSEVEN_INTRO": "Zowel KoalaSync als TwoSeven gebruiken dezelfde basisaanpak voor kijkfeesten: ze synchroniseren de originele videospeler rechtstreeks in uw browser, in plaats van een gecomprimeerde videofeed vanuit de cloud te streamen. Dit zorgt voor videokwaliteit van het hoogste niveau voor beide tools. Hoewel TwoSeven een commerciële portal is met ingebouwde webcamchat en abonnementsniveaus, blijft KoalaSync een minimalistische, volledig gratis en privacyvriendelijke extensie. Ontdek hier welke dienst het beste bij u past.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Wanneer TwoSeven de betere keuze is",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven is de juiste keuze als u een <strong>alles-in-één oplossing met geïntegreerde webcam en audiochat</strong> rechtstreeks in uw browser wilt. Als je je vrienden wilt zien tijdens het kijken zonder Discord of Teamspeak op de achtergrond te hoeven draaien, biedt TwoSeven deze integratie native. Bovendien werkt het voor YouTube en een paar open webvideospelers zonder extensies. Het is zeer geschikt voor kleine groepen van 2 tot 3 personen die tijdens het kijken een visuele verbinding willen delen.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Wanneer KoalaSync beter past",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync schittert met zijn <strong>volledige gebrek aan kosten, privacy en eenvoud</strong>:<br><br>• <strong>Geen betaalmuren</strong>: om premiumdiensten zoals Disney+ of Hulu synchroon te bekijken op TwoSeven, moet ten minste één kamerlid deze ondersteunen op Patreon (vanaf $ 3/maand). KoalaSync synchroniseert Netflix, Prime Video, Disney+ en zelfgehoste mediaservers (Jellyfin, Plex, Emby) 100% gratis en zonder beperkingen.<br>• <strong>Absolute privacy (geen trackers/advertenties)</strong>: TwoSeven wordt door advertenties ondersteund en gebruikt meerdere trackers van Google, Facebook en anderen. KoalaSync heeft geen advertenties, geen trackers en communiceert uitsluitend met de relay-server met alleen RAM.<br>• <strong>Geen registratie vereist</strong>: TwoSeven vereist dat alle deelnemers een account aanmaken en inloggen. KoalaSync is volledig accountvrij. Gewoon installeren, een kamercode invoeren en beginnen met kijken.<br>• <strong>Lichtgewicht en gebruiksvriendelijk</strong>: de geïntegreerde webcam en audiofeeds van TwoSeven belasten uw CPU en netwerk zwaar. Door de communicatie over te laten aan tools als Discord, werkt KoalaSync uiterst soepel en wordt de levensduur van de batterij verlengd.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "Het belangrijkste verschil",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven is een <strong>commercieel platform</strong> met registratievereisten, advertenties, peer-to-peer webcamchats en Patreon-betaalmuren voor specifieke streamingdiensten. KoalaSync is een <strong>gratis, open-source hulpprogramma</strong> dat rechtstreeks op uw browsertabbladen aansluit, zonder accounts, trackers of extra kosten, waardoor u zonder afleiding kunt kijken in de native speler.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Eerlijke beperkingen",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync biedt <strong>geen ingebouwde webcam of audiochat</strong> en gaat ervan uit dat je al aan het bellen bent via Discord of een soortgelijke tool. Bovendien heeft KoalaSync geen ingebouwde chatbox-overlay en is deze momenteel alleen op de desktop beschikbaar.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Kortom",
"ALT_TWOSEVEN_SUMMARY_BODY": "Voor kleine groepjes van twee of drie personen die elkaar via webcams direct in de browser willen zien en het niet erg vinden om een Patreon voor Disney+ ondersteuning te ondersteunen, is TwoSeven een leuke optie. Voor advertentievrije, volledig gratis en privéfilmavonden in native 4K-kwaliteit (of het nu Netflix, Prime Video, Disney+ of Jellyfin is) zonder registratie, is KoalaSync de schonere en veiligere keuze.",
"ALT_TRY_KOALASYNC": "Probeer KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Hostbeheer",
"MOCK_HOST_CONTROL_TOGGLE": "Alleen ik mag de weergave bedienen",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync nie zastępuje rozmowy głosowej. Jeśli chcesz rozmawiać podczas oglądania, nadal możesz korzystać z Discorda, TeamSpeaka, Signala, WhatsAppa lub innych narzędzi, których używasz na co dzień.<br><br>Każda osoba musi również mieć dostęp do filmu lub strony na własnym urządzeniu. KoalaSync nie omija subskrypcji, konieczności logowania, zabezpieczeń DRM, ograniczeń regionalnych ani regulaminów platform.<br><br>Obecnie rozwiązanie to działa tylko w przeglądarkach na komputerach stacjonarnych i nie posiada wbudowanego czatu ani funkcji komunikacji głosowej, a kompatybilność zależy od używanej przeglądarki oraz odtwarzacza wideo.",
"ALT_SCREEN_SUMMARY_TITLE": "Podsumowanie",
"ALT_SCREEN_SUMMARY_BODY": "Udostępnianie ekranu to najprostsze rozwiązanie, gdy zależy Ci na szybkości, a kwestie jakości, prywatności czy indywidualnej kontroli nad odtwarzaniem nie są priorytetem. KoalaSync sprawdza się lepiej, gdy uczestnicy oglądają materiał lokalnie we własnych przeglądarkach, a sesja ma bardziej przypominać wspólny seans.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Które rozwiązanie do oglądania filmów pasuje lepiej?",
"ALT_W2G_META_DESC": "Uczciwe porównanie między KoalaSync i Watch2Gether. Odkryj, kiedy elastyczność KoalaSync jest nie do pobicia i dlaczego Watch2Gether jest nadal najlepszym wyborem dla YouTube.",
"ALT_W2G_INTRO": "Zarówno KoalaSync, jak i Watch2Gether rozwiązują ten sam problem: oglądanie filmów zsynchronizowanych ze znajomymi online bez ręcznej koordynacji. Podczas gdy Watch2Gether jest jednym z najstarszych i najpopularniejszych ośrodków wspólnych wieczorów filmowych, KoalaSync przyjmuje zupełnie inne, lekkie podejście. To, które narzędzie będzie dla Ciebie odpowiednie, zależy w dużej mierze od tego, co i gdzie chcesz oglądać.",
"ALT_W2G_WHEN_W2G_TITLE": "Kiedy Watch2Gether jest lepszym wyborem",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether jest nie do pobicia w przypadku <strong>imprez oglądania w YouTube</strong>. Dzięki wbudowanej liście odtwarzania i wyszukiwaniu każdy w pomieszczeniu może z łatwością znajdować, dodawać i odtwarzać nowe filmy. Wszyscy płynnie oglądają wspólnie kolejny film.<br><br>Dzięki KoalaSync w YouTube przejmuje domyślną funkcję autoodtwarzania witryny, przekierowując każdego użytkownika do innego polecanego filmu. Nasza automatyczna funkcja następnego odcinka („Lobby odcinków”), która świetnie sprawdza się w serwisach Netflix i Disney+, nie działa w YouTube ze względu na te dynamiczne rekomendacje. Jeśli chcesz spędzić czas wyłącznie na YouTube, lepszym wyborem będzie Watch2Gether.",
"ALT_W2G_WHEN_KOALA_TITLE": "Kiedy KoalaSync lepiej pasuje",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync wyróżnia się <strong>prawdziwymi usługami przesyłania strumieniowego</strong> (Netflix, Prime Video, Disney+) i hostowanymi serwerami multimediów (Jellyfin, Plex, Emby). W przeciwieństwie do Watch2Gether, który często w ogóle nie może odtwarzać treści premium, KoalaSync synchronizuje natywny odtwarzacz bezpośrednio na stronie internetowej.<br><br>Działa na prawie każdej witrynie wyposażonej w standardowy odtwarzacz wideo HTML5. Nie musisz konfigurować wirtualnego pokoju na stronie trzeciej: po prostu aktywuj rozszerzenie, dołącz do lobby i zacznij oglądać.",
"ALT_W2G_MAIN_DIFF_TITLE": "Główna różnica",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether to <strong>samodzielna witryna</strong> z wbudowanym czatem, listami odtwarzania i obsługą kamery internetowej. KoalaSync to <strong>minimalistyczne rozszerzenie przeglądarki</strong>, które można podłączyć bezpośrednio do zwykłych kart przeglądarki.<br><br>Szukasz wszechstronnego pakietu dla YouTube z wbudowanym czatem? Użyj Watch2Gether. Chcesz oglądać filmy w serwisie Netflix lub na własnym serwerze bez zakłóceń, w natywnej jakości (bez kompresji serwerowej)? KoalaSync to czystsze rozwiązanie.",
"ALT_W2G_LIMITS_TITLE": "Uczciwe ograniczenia",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>nie ma wbudowanych list odtwarzania ani wyszukiwania filmów</strong>. W YouTube oznacza to, że automatyczne odtwarzanie następnego filmu nie będzie zsynchronizowane.<br><br>Dodatkowo <strong>nie ma wbudowanego czatu</strong>, a KoalaSync działa obecnie tylko w przeglądarkach na komputerze. Został zaprojektowany przy założeniu, że i tak rozmawiasz przez Discord, Teamspeak lub inne narzędzia głosowe.",
"ALT_W2G_SUMMARY_TITLE": "Krótko mówiąc",
"ALT_W2G_SUMMARY_BODY": "W przypadku spontanicznych sesji YouTube z playlistami i wbudowanym czatem najlepszym wyborem będzie Watch2Gether. W przypadku platform do przesyłania strumieniowego premium (takich jak Netflix, Prime Video, Disney+), serwerów hostowanych samodzielnie (Jellyfin, Plex, Emby) i maksymalnej elastyczności przeglądarki, KoalaSync jest bardziej odpowiednim i lekkim narzędziem.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: która platforma do oglądania filmów pasuje lepiej?",
"ALT_SCENER_META_DESC": "Uczciwe porównanie KoalaSync i Scener. Dowiedz się, kiedy wygrywa czat z kamerą internetową Scener i dlaczego KoalaSync jest najlepszy na wieczory filmowe pozbawione zakłóceń.",
"ALT_SCENER_INTRO": "KoalaSync i Scener pozwalają oglądać imprezy z dwóch zupełnie różnych perspektyw. Scener to wirtualne kino z wbudowanym czatem wideo i pokojami interaktywnymi. Z kolei KoalaSync to minimalistyczne, przyjazne dla prywatności rozszerzenie przeglądarki, które po prostu synchronizuje sterowanie odtwarzaniem. To, które narzędzie będzie dla Ciebie najbardziej odpowiednie, zależy głównie od tego, jak ważna jest dla Ciebie wbudowana kamera internetowa i funkcje czatu.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Kiedy Scener jest lepszym wyborem",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener to solidny wybór, jeśli potrzebujesz <strong>uniwersalnej platformy społecznościowej</strong> z wbudowanym czatem wideo i audio bezpośrednio w przeglądarce. Scener tworzy wirtualny pokój, w którym kamery internetowe gracza i znajomych są wyświetlane obok siebie. Jest to idealne rozwiązanie w przypadku dużych, publicznych imprez związanych z oglądaniem lub wirtualnych wydarzeń transmitowanych strumieniowo, gdzie aspekt społecznościowy jest na pierwszym miejscu. Należy jednak pamiętać, że bezpłatna wersja podstawowa obsługuje reklamy, a Scener blokuje wiele funkcji (takich jak oglądanie bez reklam i nieograniczone czaty wideo) w ramach miesięcznej subskrypcji (5,79 USD miesięcznie lub 39,99 USD rocznie).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Kiedy KoalaSync lepiej pasuje",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync wyróżnia się <strong>jakością wideo, prywatnością i prostotą</strong>: <br><br> • <strong>Brak kont</strong>: nie musisz się rejestrować, logować ani zarządzać profilami. Po prostu aktywuj rozszerzenie, udostępnij kod pokoju i zacznij oglądać.<br> • <strong>Prawdziwa jakość natywna (4K/HDR)</strong>: Scener przesyła strumieniowo skompresowany obraz wideo z wirtualnego serwera w chmurze, co może prowadzić do utraty jakości i opóźnień. KoalaSync synchronizuje natywny odtwarzacz bezpośrednio na Twoim komputerze, co oznacza, że możesz oglądać filmy w pełnej rozdzielczości swojej subskrypcji strumieniowej.<br> • <strong>Niskie wykorzystanie przepustowości</strong>: Ponieważ przesyłane są tylko dane sterujące (odtwarzanie, pauza, znaczniki czasu), KoalaSync praktycznie nie wykorzystuje dodatkowej przepustowości. Scener przesyła strumieniowo cały obraz wideo i kamery przez serwery w chmurze, co może znacznie obciążać wolniejsze połączenia internetowe i starsze laptopy.<br> • <strong>100% za darmo i bez reklam</strong>: brak miesięcznych opłat abonamentowych, brak reklam i modułów śledzących.<br> • <strong>Lokalne pliki wideo</strong>: ponieważ KoalaSync działa lokalnie, możesz nawet oglądać własne pliki wideo (takie jak MP4) synchronizowane ze znajomymi. Po prostu przeciągnij i upuść plik na kartę przeglądarki Scener nie może tego zrobić, ponieważ jego odtwarzacz działa w chmurze.",
"ALT_SCENER_MAIN_DIFF_TITLE": "Główna różnica",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener to <strong>komercyjna sieć społecznościowa</strong> dla grup obserwujących, obsługiwana przez przeglądarki w wirtualnej chmurze i finansowana z reklam i miesięcznych subskrypcji. KoalaSync to <strong>bezpłatne narzędzie do synchronizacji, które dba o prywatność</strong>, które łączy się bezpośrednio z kartami przeglądarki. Pozostawia czat głosowy/wideo aplikacjom takim jak Discord lub Teamspeak, skupiając się całkowicie na zapewnieniu płynności odtwarzania, prywatności i oryginalnej jakości natywnej.",
"ALT_SCENER_LIMITS_TITLE": "Uczciwe ograniczenia",
"ALT_SCENER_LIMITS_BODY": "KoalaSync <strong>nie oferuje wbudowanego czatu ani obsługi kamery internetowej</strong>. Jest to wyłącznie narzędzie do synchronizacji i wymaga wybranego przez Ciebie osobnego narzędzia do połączeń głosowych. Ponadto KoalaSync jest obecnie dostępny tylko na komputerach stacjonarnych, a zgodność lokalnych plików wideo zależy całkowicie od tego, czy Twoja przeglądarka natywnie obsługuje odtwarzanie formatu wideo i kodeków audio.",
"ALT_SCENER_SUMMARY_TITLE": "Krótko mówiąc",
"ALT_SCENER_SUMMARY_BODY": "W przypadku dużych imprez oglądania z wbudowanym czatem kamery internetowej i funkcjami społecznościowymi Scener jest właściwym wyborem, pod warunkiem, że nie przeszkadzają Ci reklamy i płatne ściany premium. Jeśli chcesz korzystać z całkowicie darmowego, wolnego od reklam i zakłóceń doświadczenia w natywnym odtwarzaczu (w tym Netflix, Prime Video, Disney+ lub pliki lokalnej przeglądarki) i już prowadzisz połączenie głosowe, KoalaSync jest czystszym i wydajniejszym rozwiązaniem.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: która alternatywa imprezy Netflix pasuje lepiej?",
"ALT_KOSMI_META_DESC": "Uczciwe porównanie KoalaSync i Kosmi. Dowiedz się, dlaczego konfiguracja Kosmi bez rozszerzenia jest wygodna i kiedy wygrywa natywna jakość wideo KoalaSync.",
"ALT_KOSMI_INTRO": "Zarówno KoalaSync, jak i Kosmi oferują świetne sposoby na synchronizację oglądania Netflix, YouTube i innych platform ze znajomymi. Jednak ich podstawowe technologie różnią się zasadniczo. Kosmi korzysta z przeglądarek w chmurze wirtualnej, które działają bezpośrednio w przeglądarce internetowej, bez konieczności instalowania rozszerzeń. KoalaSync to lekkie rozszerzenie, które synchronizuje lokalny odtwarzacz wideo. To, które podejście będzie dla Ciebie najbardziej odpowiednie, zależy od Twoich priorytetów dotyczących jakości wideo, wygody i prywatności.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Kiedy Kosmi jest lepszym wyborem",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi jest nie do pobicia, jeśli chcesz <strong>unikać instalowania czegokolwiek</strong> lub chcesz oglądać na urządzeniach takich jak tablety i smartfony. Ponieważ Kosmi uruchamia wirtualne przeglądarki w chmurze, aby dołączyć, wystarczy proste łącze internetowe. Co więcej, Kosmi to uniwersalna platforma do spotkań: oprócz zsynchronizowanego przesyłania strumieniowego, możesz grać w gry wieloosobowe (takie jak klasyki retro NES/SNES lub poker) oraz korzystać z wbudowanej kamery internetowej, czatu głosowego i tekstowego. Jeśli chcesz zorganizować wieczór gier towarzyskich i obejrzeć imprezę bez konfiguracji, Kosmi to fantastyczne rozwiązanie.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Kiedy KoalaSync lepiej pasuje",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync wyróżnia się <strong>natywną jakością odtwarzania, bezpieczeństwem i wydajnością</strong>: <br><br> • <strong>Brak zagrożeń bezpieczeństwa</strong>: dzięki Kosmi musisz zalogować się do swojego konta Netflix lub Prime na zdalnym komputerze wirtualnym w chmurze. Dzięki KoalaSync logujesz się bezpiecznie na oficjalnej stronie przesyłania strumieniowego w swojej przeglądarce, tak jak zwykle. Twoje hasła nigdy nie opuszczają Twojego komputera.<br> • <strong>Pełna jakość wideo (4K/HDR)</strong>: Kosmi przesyła strumieniowo ekran wirtualnej przeglądarki jako skompresowany obraz wideo, co może powodować pikselację i buforowanie. KoalaSync synchronizuje natywne odtwarzacze lokalnie: możesz cieszyć się filmami w pełnej, krystalicznie czystej rozdzielczości swojej subskrypcji.<br> • <strong>Bez opóźnień i przyjazna przepustowość</strong>: Ponieważ KoalaSync wysyła tylko polecenia sterujące (odtwarzanie/pauza/znaczniki czasu), wykorzystuje prawie zerową przepustowość. Kosmi stale przesyła strumieniowo strumienie wideo HD, co może przeciążyć wolniejsze połączenia.<br> • <strong>Lokalne pliki wideo</strong>: jeśli chcesz obejrzeć prywatny film, po prostu przeciągnij i upuść plik MP4 na kartę przeglądarki i zsynchronizuj go. Kosmi nie może uzyskać dostępu do plików na lokalnym dysku twardym.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "Główna różnica",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi to <strong>wirtualne spotkanie w chmurze</strong>, które przesyła strumieniowo ekran zdalnej przeglądarki, dzięki czemu nikt nie musi instalować rozszerzenia. KoalaSync to <strong>lokalna warstwa synchronizacji przeglądarki</strong>, która łączy się bezpośrednio z natywnym odtwarzaczem na oficjalnej stronie przesyłania strumieniowego. Podczas gdy Kosmi jest bardziej wszechstronna pod względem minigier i kompatybilności z urządzeniami, KoalaSync oferuje bezpieczniejsze, płynniejsze i ostrzejsze przesyłanie strumieniowe w oryginalnym odtwarzaczu.",
"ALT_KOSMI_LIMITS_TITLE": "Uczciwe ograniczenia",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>wymaga zainstalowania rozszerzenia przeglądarki</strong> i obecnie działa tylko na komputerach stacjonarnych. <strong>Nie ma wbudowanego czatu ani kamer internetowych</strong>, ponieważ został zaprojektowany przy założeniu, że i tak rozmawiasz przez Discord lub inne narzędzia głosowe. Nie oferuje również wbudowanych gier.",
"ALT_KOSMI_SUMMARY_TITLE": "Krótko mówiąc",
"ALT_KOSMI_SUMMARY_BODY": "Na nieformalne wieczory z grami z klasykami w stylu retro i łatwym dostępem na urządzeniach mobilnych bez żadnej instalacji, Kosmi jest idealnym rozwiązaniem. W przypadku wieczorów filmowych premium w serwisach Netflix, Prime Video, Disney+ lub Plex w pełnej jakości 4K, przy maksymalnym bezpieczeństwie i minimalnym wpływie na przepustowość, KoalaSync jest wyraźnym zwycięzcą.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: Które rozwiązanie do oglądania filmów pasuje lepiej?",
"ALT_TWOSEVEN_META_DESC": "Uczciwe porównanie KoalaSync i TwoSeven. Dowiedz się, kiedy wbudowana kamera internetowa TwoSeven wygrywa i dlaczego KoalaSync jest najlepszy dla Disney+ i Netflix.",
"ALT_TWOSEVEN_INTRO": "Zarówno KoalaSync, jak i TwoSeven stosują to samo podstawowe podejście do oglądania imprez: synchronizują oryginalny odtwarzacz wideo bezpośrednio w przeglądarce, zamiast przesyłać strumieniowo skompresowany strumień wideo z chmury. Zapewnia to najwyższą jakość wideo dla obu narzędzi. Jednakże, chociaż TwoSeven jest portalem komercyjnym z wbudowanym czatem z kamerą internetową i poziomami subskrypcji, KoalaSync pozostaje minimalistycznym, całkowicie darmowym i przyjaznym dla prywatności rozszerzeniem. Tutaj dowiesz się, która usługa najbardziej Ci odpowiada.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Kiedy TwoSeven jest lepszym wyborem",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven to właściwy wybór, jeśli potrzebujesz <strong>kompleksowego rozwiązania ze zintegrowaną kamerą internetową i czatem audio</strong> bezpośrednio w przeglądarce. Jeśli chcesz widzieć swoich znajomych podczas oglądania, bez konieczności uruchamiania Discorda lub Teamspeaka w tle, TwoSeven oferuje tę integrację natywnie. Dodatkowo działa z YouTube i kilkoma otwartymi internetowymi odtwarzaczami wideo bez rozszerzeń. Jest odpowiedni dla małych grup składających się z 2 do 3 osób, które chcą dzielić połączenie wizualne podczas oglądania.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Kiedy KoalaSync lepiej pasuje",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync wyróżnia się <strong>całkowitym brakiem opłat, prywatności i prostotą</strong>: <br><br> • <strong>Brak płatnych usług</strong>: aby oglądać usługi premium, takie jak Disney+ czy Hulu zsynchronizowane w TwoSeven, co najmniej jeden członek pokoju musi je wspierać na Patreonie (od 3 USD/miesiąc). KoalaSync synchronizuje Netflix, Prime Video, Disney+ i własne serwery multimediów (Jellyfin, Plex, Emby) w 100% bezpłatnie i bez ograniczeń.<br> • <strong>Absolutna prywatność (bez modułów śledzących/reklam)</strong>: TwoSeven obsługuje reklamy i korzysta z wielu modułów śledzących z Google, Facebooka i innych. KoalaSync nie zawiera reklam ani modułów śledzących i komunikuje się wyłącznie z serwerem przekazującym wyposażonym wyłącznie w pamięć RAM.<br> • <strong>Nie jest wymagana rejestracja</strong>: TwoSeven wymaga od wszystkich uczestników utworzenia konta i zalogowania się. KoalaSync jest całkowicie pozbawiony konta. Po prostu zainstaluj, wprowadź kod pokoju i zacznij oglądać.<br> • <strong>Lekki i przyjazny dla zasobów</strong>: Zintegrowana kamera internetowa TwoSeven i kanały audio mocno obciążają Twój procesor i sieć. Pozostawiając komunikację narzędziom takim jak Discord, KoalaSync działa niezwykle płynnie i oszczędza baterię.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "Główna różnica",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven to <strong>platforma komercyjna</strong> z wymogami rejestracyjnymi, reklamami, czatami przed kamerą internetową typu peer-to-peer i zaporami Patreon dla określonych usług przesyłania strumieniowego. KoalaSync to <strong>darmowe narzędzie o otwartym kodzie źródłowym</strong>, które łączy się bezpośrednio z kartami przeglądarki, bez konieczności zakładania kont, modułów śledzących i dodatkowych kosztów, umożliwiając oglądanie bez rozpraszania uwagi w natywnym odtwarzaczu.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Uczciwe ograniczenia",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync <strong>nie ma wbudowanej kamery internetowej ani czatu audio</strong> i zakłada, że prowadzisz już rozmowę za pośrednictwem Discorda lub podobnego narzędzia. Ponadto KoalaSync nie ma wbudowanej nakładki okna czatu i jest obecnie dostępny tylko na komputerze.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Krótko mówiąc",
"ALT_TWOSEVEN_SUMMARY_BODY": "Dla małych grup składających się z dwóch lub trzech osób, które chcą widzieć się nawzajem za pośrednictwem kamer internetowych bezpośrednio w przeglądarce i nie mają nic przeciwko wspieraniu Patreona w ramach obsługi Disney+, TwoSeven jest fajną opcją. W przypadku wolnych od reklam, całkowicie bezpłatnych i prywatnych wieczorów filmowych w natywnej jakości 4K (Netflix, Prime Video, Disney+ lub Jellyfin) bez rejestracji, KoalaSync jest czystszym i bezpieczniejszym wyborem.",
"ALT_TRY_KOALASYNC": "Wypróbuj KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Kontrola hosta",
"MOCK_HOST_CONTROL_TOGGLE": "Tylko ja mogę sterować odtwarzaniem",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "O KoalaSync não substitui uma chamada de voz. Se você quiser conversar enquanto assiste, continue usando Discord, Teamspeak, Signal, WhatsApp ou qualquer ferramenta que utilize normalmente.<br><br>Todos também precisam ter acesso ao vídeo ou à página em seus próprios dispositivos. O KoalaSync não contorna assinaturas, logins, DRM, restrições regionais ou regras da plataforma.<br><br>Atualmente, funciona apenas em navegadores para desktop, não possui recursos integrados de chat ou voz, e a compatibilidade depende sempre do navegador e do reprodutor de vídeo.",
"ALT_SCREEN_SUMMARY_TITLE": "Resumo",
"ALT_SCREEN_SUMMARY_BODY": "O compartilhamento de tela é a opção mais simples quando você quer algo rápido e não se preocupa muito com qualidade, privacidade ou controle individual. O KoalaSync é mais adequado quando todos devem assistir localmente em seus próprios navegadores e a sessão deve proporcionar uma experiência mais próxima de realmente assistir juntos.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Qual solução de watch party se adapta melhor?",
"ALT_W2G_META_DESC": "Uma comparação honesta entre KoalaSync e Watch2Gether. Descubra quando a flexibilidade do KoalaSync é imbatível e por que o Watch2Gether ainda é a melhor escolha para o YouTube.",
"ALT_W2G_INTRO": "KoalaSync e Watch2Gether resolvem o mesmo problema: assistir vídeos sincronizados com amigos online sem coordenação manual. Embora Watch2Gether seja um dos centros mais antigos e populares para noites de cinema compartilhadas, o KoalaSync adota uma abordagem leve e completamente diferente. A ferramenta certa para você depende muito do que e onde você deseja assistir.",
"ALT_W2G_WHEN_W2G_TITLE": "Quando Watch2Gether é a melhor escolha",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether é imbatível para <strong>festas de exibição do YouTube</strong>. Com sua lista de reprodução e pesquisa integradas, qualquer pessoa na sala pode facilmente encontrar, adicionar e reproduzir novos vídeos. Todos assistem ao próximo vídeo juntos sem problemas.<br><br>Com o KoalaSync no YouTube, a reprodução automática padrão do site assume o controle, redirecionando cada usuário para um vídeo recomendado diferente. Nosso recurso automático de próximo episódio (“Episode Lobby), que funciona muito bem no Netflix ou Disney+, não funciona no YouTube devido a essas recomendações dinâmicas. Para noites puras no YouTube, Watch2Gether é a melhor escolha.",
"ALT_W2G_WHEN_KOALA_TITLE": "Quando o KoalaSync se ajusta melhor",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync brilha em <strong>serviços reais de streaming</strong> (Netflix, Prime Video, Disney+) e servidores de mídia auto-hospedados (Jellyfin, Plex, Emby). Ao contrário do Watch2Gether, que muitas vezes não consegue reproduzir conteúdo premium, o KoalaSync sincroniza o player nativo diretamente no site.<br><br>Ele funciona em quase todos os sites com um player de vídeo HTML5 padrão. Você não precisa configurar uma sala virtual em um site de terceiros: basta ativar a extensão, entrar em um lobby e começar a assistir.",
"ALT_W2G_MAIN_DIFF_TITLE": "A principal diferença",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether é um <strong>site independente</strong> com chat integrado, listas de reprodução e suporte para webcam. KoalaSync é uma <strong>extensão de navegador minimalista</strong> que se conecta diretamente às guias normais do navegador.<br><br>Procurando um pacote completo para o YouTube com bate-papo integrado? Use Watch2Gether. Quer assistir filmes na Netflix ou no seu próprio servidor sem distrações, em qualidade nativa (sem compactação do servidor)? KoalaSync é a solução mais limpa.",
"ALT_W2G_LIMITS_TITLE": "Limitações honestas",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>não possui listas de reprodução integradas ou pesquisa de vídeos</strong>. No YouTube, isso significa que a reprodução automática do próximo vídeo não permanecerá sincronizada.<br><br>Além disso, <strong>não há bate-papo integrado</strong>, e o KoalaSync atualmente só funciona em navegadores de desktop. Ele foi projetado partindo do pressuposto de que você já está falando via Discord, Teamspeak ou outras ferramentas de voz.",
"ALT_W2G_SUMMARY_TITLE": "Resumidamente",
"ALT_W2G_SUMMARY_BODY": "Para sessões espontâneas no YouTube com playlists e chat integrado, Watch2Gether é a melhor escolha. Para plataformas de streaming premium (como Netflix, Prime Video, Disney+), servidores auto-hospedados (Jellyfin, Plex, Emby) e flexibilidade máxima do navegador, KoalaSync é a ferramenta mais adequada e leve.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: Qual plataforma de watch party se adapta melhor?",
"ALT_SCENER_META_DESC": "Uma comparação honesta entre KoalaSync e Scener. Descubra quando o bate-papo na webcam do Scener vence e por que o KoalaSync é melhor para noites de cinema sem distrações.",
"ALT_SCENER_INTRO": "KoalaSync e Scener abordam festas de dois ângulos completamente diferentes. Scener é uma sala de cinema virtual com chat de vídeo integrado e salas interativas. KoalaSync, por outro lado, é uma extensão de navegador minimalista e amigável à privacidade que simplesmente sincroniza os controles de reprodução. A ferramenta mais adequada para você depende principalmente da importância dos recursos integrados de webcam e bate-papo para você.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Quando Scener é a melhor escolha",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener é uma escolha sólida se você deseja uma <strong>plataforma social completa</strong> com bate-papo por vídeo e áudio integrado diretamente em seu navegador. O Scener cria uma sala virtual onde as webcams do jogador e dos seus amigos são exibidas lado a lado. Isso é ideal para grandes festas públicas ou eventos de streaming virtual onde o aspecto social é o centro das atenções. No entanto, lembre-se de que a versão básica gratuita é suportada por anúncios e o Scener bloqueia muitos recursos (como visualização sem anúncios e chat de vídeo ilimitado) por meio de uma assinatura mensal (US$ 5,79/mês ou US$ 39,99/ano).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Quando o KoalaSync se ajusta melhor",
"ALT_SCENER_WHEN_KOALA_BODY": "O KoalaSync brilha quando se trata de <strong>qualidade, privacidade e simplicidade de vídeo</strong>:<br><br>• <strong>Sem contas</strong>: você não precisa se registrar, fazer login ou gerenciar perfis. Basta ativar a extensão, compartilhar um código de sala e começar a assistir.<br>• <strong>Qualidade nativa real (4K/HDR)</strong>: o Scener transmite vídeo compactado de um servidor virtual em nuvem, o que pode levar à perda de qualidade e atrasos. O KoalaSync sincroniza o player nativo diretamente no seu computador, o que significa que você assiste filmes na resolução total da sua assinatura de streaming.<br>• <strong>Baixo uso de largura de banda</strong>: como apenas dados de controle (reprodução, pausa, registros de data e hora) são transmitidos, o KoalaSync praticamente não usa largura de banda extra. O Scener transmite todos os feeds de vídeo e câmera por meio de servidores em nuvem, o que pode sobrecarregar muito conexões de Internet mais lentas e laptops mais antigos.<br>• <strong>100% gratuito e sem anúncios</strong>: sem taxas de assinatura mensal, sem anúncios e sem rastreadores.<br>• <strong>Arquivos de vídeo locais</strong>: como o KoalaSync é executado localmente, você pode até assistir seus próprios arquivos de vídeo (como MP4) em sincronia com amigos. Basta arrastar e soltar o arquivo em uma guia do navegador o Scener não pode fazer isso porque seu player roda na nuvem.",
"ALT_SCENER_MAIN_DIFF_TITLE": "A principal diferença",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener é uma <strong>rede social comercial</strong> para assistir festas que é alimentada por navegadores virtuais em nuvem e financiada por anúncios e assinaturas mensais. KoalaSync é um <strong>utilitário de sincronização gratuito e com foco na privacidade</strong> que se conecta diretamente às guias do seu navegador. Ele deixa o bate-papo por voz/vídeo para aplicativos como Discord ou Teamspeak, concentrando-se inteiramente em manter sua reprodução fluida, privada e em sua qualidade original nativa.",
"ALT_SCENER_LIMITS_TITLE": "Limitações honestas",
"ALT_SCENER_LIMITS_BODY": "KoalaSync <strong>não oferece suporte integrado para chat ou webcam</strong>. É puramente uma ferramenta de sincronização e requer uma ferramenta de chamada de voz separada de sua escolha. Além disso, o KoalaSync atualmente é apenas para desktop, e a compatibilidade do arquivo de vídeo local depende inteiramente se o seu navegador suporta nativamente a reprodução do formato de vídeo e codecs de áudio.",
"ALT_SCENER_SUMMARY_TITLE": "Resumidamente",
"ALT_SCENER_SUMMARY_BODY": "Para grandes grupos de observação com bate-papo na webcam integrado e recursos sociais, o Scener é a escolha certa, desde que você não se importe com anúncios e acessos pagos premium. Se você deseja uma experiência totalmente gratuita, sem anúncios e sem distrações no player nativo (incluindo Netflix, Prime Video, Disney+ ou arquivos de navegador local) e já está em uma chamada de voz, o KoalaSync é a solução mais limpa e com melhor desempenho.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: Qual alternativa de festa da Netflix se adapta melhor?",
"ALT_KOSMI_META_DESC": "Uma comparação honesta entre KoalaSync e Kosmi. Descubra por que a configuração sem extensão do Kosmi é conveniente e quando a qualidade de vídeo nativa do KoalaSync vence.",
"ALT_KOSMI_INTRO": "Tanto o KoalaSync quanto o Kosmi oferecem ótimas maneiras de assistir Netflix, YouTube e outras plataformas em sincronia com amigos. No entanto, as suas tecnologias subjacentes são fundamentalmente diferentes. Kosmi usa navegadores virtuais em nuvem que são executados diretamente em seu navegador sem instalar extensões. KoalaSync é uma extensão leve que sincroniza seu player de vídeo local. A abordagem mais adequada para você depende de suas prioridades em relação à qualidade, conveniência e privacidade do vídeo.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Quando Kosmi é a melhor escolha",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi é imbatível se você quiser <strong>evitar instalar qualquer coisa</strong> ou quiser assistir em dispositivos como tablets e smartphones. Como o Kosmi executa navegadores virtuais na nuvem, basta um simples link da web para ingressar. Além disso, Kosmi é uma plataforma de hangout completa: além do streaming sincronizado, você pode jogar jogos multijogador (como clássicos retrô do NES/SNES ou pôquer) e usar a webcam integrada, bate-papo por voz e texto. Se você quer uma noite de jogos sociais e assistir a uma festa sem configuração, Kosmi é uma solução fantástica.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Quando o KoalaSync se ajusta melhor",
"ALT_KOSMI_WHEN_KOALA_BODY": "O KoalaSync brilha quando se trata de <strong>qualidade de reprodução, segurança e desempenho nativos</strong>:<br><br>• <strong>Sem riscos de segurança</strong>: com o Kosmi, você precisa fazer login na sua conta Netflix ou Prime em um computador virtual remoto na nuvem. Com o KoalaSync, você faz login com segurança no site oficial de streaming em seu próprio navegador, como faria normalmente. Suas senhas nunca saem da sua máquina.<br>• <strong>Qualidade total de vídeo (4K/HDR)</strong>: o Kosmi transmite a tela do navegador virtual como um feed de vídeo compactado, o que pode resultar em pixelização e buffer. O KoalaSync sincroniza os players nativos localmente: você desfruta de filmes na resolução completa e nítida da sua assinatura.<br>• <strong>Sem atraso e compatível com largura de banda</strong>: como o KoalaSync envia apenas comandos de controle (reproduzir/pausar/carimbos de data/hora), ele usa quase zero largura de banda. Kosmi transmite constantemente feeds de vídeo em HD, o que pode sobrecarregar conexões mais lentas.<br>• <strong>Arquivos de vídeo locais</strong>: se quiser assistir a um vídeo privado, basta arrastar e soltar o arquivo MP4 em uma guia do navegador e sincronizá-lo. Kosmi não pode acessar arquivos em seu disco rígido local.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "A principal diferença",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi é um <strong>ponto de encontro virtual na nuvem</strong> que transmite a tela de um navegador remoto para que ninguém precise instalar uma extensão. KoalaSync é uma <strong>camada de sincronização local do navegador</strong> que se conecta diretamente ao player nativo no site oficial de streaming. Embora o Kosmi seja mais versátil para minijogos e compatibilidade de dispositivos, o KoalaSync oferece uma experiência de streaming mais segura, fluida e nítida no player original.",
"ALT_KOSMI_LIMITS_TITLE": "Limitações honestas",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>requer a instalação de uma extensão de navegador</strong> e atualmente só funciona em PCs desktop. Ele <strong>não possui bate-papo ou webcams integrados</strong>, pois foi projetado sob a suposição de que você já está conversando via Discord ou outras ferramentas de voz. Também não oferece jogos integrados.",
"ALT_KOSMI_SUMMARY_TITLE": "Resumidamente",
"ALT_KOSMI_SUMMARY_BODY": "Para noites de jogos casuais com clássicos retrô e fácil acesso em dispositivos móveis sem qualquer instalação, o Kosmi é ideal. Para noites de cinema premium no Netflix, Prime Video, Disney+ ou Plex em qualidade 4K total, com segurança máxima e impacto mínimo na largura de banda, o KoalaSync é o vencedor claro.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: Qual solução de watch party se adapta melhor?",
"ALT_TWOSEVEN_META_DESC": "Uma comparação honesta entre KoalaSync e TwoSeven. Descubra quando a webcam integrada do TwoSeven vence e por que o KoalaSync é melhor para Disney+ e Netflix.",
"ALT_TWOSEVEN_INTRO": "Tanto o KoalaSync quanto o TwoSeven usam a mesma abordagem básica para assistir grupos: eles sincronizam o player de vídeo original diretamente no seu navegador, em vez de transmitir um feed de vídeo compactado da nuvem. Isso garante qualidade de vídeo de alto nível para ambas as ferramentas. No entanto, embora o TwoSeven seja um portal comercial com chat de webcam integrado e níveis de assinatura, o KoalaSync continua sendo uma extensão minimalista, totalmente gratuita e com privacidade. Descubra aqui qual serviço se adapta melhor a você.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Quando TwoSeven é a melhor escolha",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven é a escolha certa se você deseja uma <strong>solução completa com webcam integrada e chat de áudio</strong> diretamente no seu navegador. Se você quiser ver seus amigos enquanto assiste sem precisar rodar o Discord ou Teamspeak em segundo plano, o TwoSeven oferece essa integração de forma nativa. Além disso, funciona para o YouTube e alguns players de vídeo da web abertos sem extensões. É adequado para pequenos grupos de 2 a 3 pessoas que desejam compartilhar uma conexão visual durante a visualização.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Quando o KoalaSync se ajusta melhor",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync brilha com sua <strong>total falta de taxas, privacidade e simplicidade</strong>:<br><br>• <strong>Sem paywalls</strong>: para assistir serviços premium como Disney+ ou Hulu sincronizados no TwoSeven, pelo menos um membro da sala deve apoiá-los no Patreon (a partir de US$ 3/mês). KoalaSync sincroniza Netflix, Prime Video, Disney+ e servidores de mídia auto-hospedados (Jellyfin, Plex, Emby) 100% grátis e sem restrições.<br>• <strong>Privacidade absoluta (sem rastreadores/anúncios)</strong>: TwoSeven é suportado por anúncios e usa vários rastreadores do Google, Facebook e outros. O KoalaSync não tem anúncios nem rastreadores e se comunica exclusivamente com o servidor de retransmissão somente RAM.<br>• <strong>Não é necessário registro</strong>: o TwoSeven exige que todos os participantes criem uma conta e façam login. O KoalaSync é totalmente gratuito. Basta instalar, inserir um código de sala e começar a assistir.<br>• <strong>Leve e com poucos recursos</strong>: a webcam integrada e os feeds de áudio do TwoSeven sobrecarregam sua CPU e sua rede. Ao deixar a comunicação para ferramentas como o Discord, o KoalaSync funciona de forma extremamente suave e preserva a vida útil da bateria.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "A principal diferença",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven é uma <strong>plataforma comercial</strong> com requisitos de registro, anúncios, chats peer-to-peer por webcam e paywalls do Patreon para serviços de streaming específicos. KoalaSync é um <strong>utilitário gratuito e de código aberto</strong> que se conecta diretamente às guias do seu navegador sem contas, rastreadores ou custos extras, permitindo assistir sem distrações no player nativo.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Limitações honestas",
"ALT_TWOSEVEN_LIMITS_BODY": "O KoalaSync <strong>não oferece webcam integrada ou bate-papo com áudio</strong> e pressupõe que você já esteja em uma chamada via Discord ou ferramenta semelhante. Além disso, o KoalaSync não possui sobreposição de caixa de bate-papo integrada e atualmente é apenas para desktop.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Resumidamente",
"ALT_TWOSEVEN_SUMMARY_BODY": "Para pequenos grupos de duas ou três pessoas que desejam se ver através de webcams diretamente no navegador e não se importam em apoiar um Patreon para suporte Disney +, TwoSeven é uma boa opção. Para noites de cinema privadas, totalmente gratuitas e sem anúncios em qualidade 4K nativa (seja Netflix, Prime Video, Disney+ ou Jellyfin) sem registros, o KoalaSync é a escolha mais limpa e segura.",
"ALT_TRY_KOALASYNC": "Experimente o KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Controle do anfitrião",
"MOCK_HOST_CONTROL_TOGGLE": "Apenas eu posso controlar a reprodução",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "O KoalaSync não substitui uma chamada de voz. Se quiser conversar enquanto assiste, utilize ainda o Discord, Teamspeak, Signal, WhatsApp ou qualquer outra aplicação que utilize normalmente.<br><br>Todos também precisam de ter acesso ao vídeo ou à página nos seus próprios dispositivos. O KoalaSync não ignora as subscrições, logins, DRM, restrições regionais ou regras de plataforma.<br><br>Atualmente, funciona apenas em navegadores de desktop, não tem chat ou recurso de voz integrados e a compatibilidade depende sempre do navegador e do leitor de vídeo.",
"ALT_SCREEN_SUMMARY_TITLE": "Resumo",
"ALT_SCREEN_SUMMARY_BODY": "Partilhar o ecrã é a opção mais simples quando se quer algo rápido e não se liga muito à qualidade, privacidade ou controlo individual. O KoalaSync é mais adequado quando todos devem assistir localmente nos seus próprios browsers e a sessão deve parecer mais como assistir em conjunto.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Qual solução de watch party se adapta melhor?",
"ALT_W2G_META_DESC": "Uma comparação honesta entre KoalaSync e Watch2Gether. Descubra quando a flexibilidade do KoalaSync é imbatível e por que o Watch2Gether ainda é a melhor escolha para o YouTube.",
"ALT_W2G_INTRO": "KoalaSync e Watch2Gether resolvem o mesmo problema: assistir vídeos sincronizados com amigos online sem coordenação manual. Embora Watch2Gether seja um dos centros mais antigos e populares para noites de cinema compartilhadas, o KoalaSync adota uma abordagem leve e completamente diferente. A ferramenta certa para você depende muito do que e onde você deseja assistir.",
"ALT_W2G_WHEN_W2G_TITLE": "Quando Watch2Gether é a melhor escolha",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether é imbatível para <strong>festas de exibição do YouTube</strong>. Com sua lista de reprodução e pesquisa integradas, qualquer pessoa na sala pode facilmente encontrar, adicionar e reproduzir novos vídeos. Todos assistem ao próximo vídeo juntos sem problemas.<br><br>Com o KoalaSync no YouTube, a reprodução automática padrão do site assume o controle, redirecionando cada usuário para um vídeo recomendado diferente. Nosso recurso automático de próximo episódio (“Episode Lobby), que funciona muito bem no Netflix ou Disney+, não funciona no YouTube devido a essas recomendações dinâmicas. Para noites puras no YouTube, Watch2Gether é a melhor escolha.",
"ALT_W2G_WHEN_KOALA_TITLE": "Quando o KoalaSync se ajusta melhor",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync brilha em <strong>serviços reais de streaming</strong> (Netflix, Prime Video, Disney+) e servidores de mídia auto-hospedados (Jellyfin, Plex, Emby). Ao contrário do Watch2Gether, que muitas vezes não consegue reproduzir conteúdo premium, o KoalaSync sincroniza o player nativo diretamente no site.<br><br>Ele funciona em quase todos os sites com um player de vídeo HTML5 padrão. Você não precisa configurar uma sala virtual em um site de terceiros: basta ativar a extensão, entrar em um lobby e começar a assistir.",
"ALT_W2G_MAIN_DIFF_TITLE": "A principal diferença",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether é um <strong>site independente</strong> com chat integrado, listas de reprodução e suporte para webcam. KoalaSync é uma <strong>extensão de navegador minimalista</strong> que se conecta diretamente às guias normais do navegador.<br><br>Procurando um pacote completo para o YouTube com bate-papo integrado? Use Watch2Gether. Quer assistir filmes na Netflix ou no seu próprio servidor sem distrações, em qualidade nativa (sem compactação do servidor)? KoalaSync é a solução mais limpa.",
"ALT_W2G_LIMITS_TITLE": "Limitações honestas",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>não possui listas de reprodução integradas ou pesquisa de vídeos</strong>. No YouTube, isso significa que a reprodução automática do próximo vídeo não permanecerá sincronizada.<br><br>Além disso, <strong>não há bate-papo integrado</strong>, e o KoalaSync atualmente só funciona em navegadores de desktop. Ele foi projetado partindo do pressuposto de que você já está falando via Discord, Teamspeak ou outras ferramentas de voz.",
"ALT_W2G_SUMMARY_TITLE": "Resumidamente",
"ALT_W2G_SUMMARY_BODY": "Para sessões espontâneas no YouTube com playlists e chat integrado, Watch2Gether é a melhor escolha. Para plataformas de streaming premium (como Netflix, Prime Video, Disney+), servidores auto-hospedados (Jellyfin, Plex, Emby) e flexibilidade máxima do navegador, KoalaSync é a ferramenta mais adequada e leve.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: Qual plataforma de watch party se adapta melhor?",
"ALT_SCENER_META_DESC": "Uma comparação honesta entre KoalaSync e Scener. Descubra quando o bate-papo na webcam do Scener vence e por que o KoalaSync é melhor para noites de cinema sem distrações.",
"ALT_SCENER_INTRO": "KoalaSync e Scener abordam festas de dois ângulos completamente diferentes. Scener é uma sala de cinema virtual com chat de vídeo integrado e salas interativas. KoalaSync, por outro lado, é uma extensão de navegador minimalista e amigável à privacidade que simplesmente sincroniza os controles de reprodução. A ferramenta mais adequada para você depende principalmente da importância dos recursos integrados de webcam e bate-papo para você.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Quando Scener é a melhor escolha",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener é uma escolha sólida se você deseja uma <strong>plataforma social completa</strong> com bate-papo por vídeo e áudio integrado diretamente em seu navegador. O Scener cria uma sala virtual onde as webcams do jogador e dos seus amigos são exibidas lado a lado. Isso é ideal para grandes festas públicas ou eventos de streaming virtual onde o aspecto social é o centro das atenções. No entanto, lembre-se de que a versão básica gratuita é suportada por anúncios e o Scener bloqueia muitos recursos (como visualização sem anúncios e chat de vídeo ilimitado) por meio de uma assinatura mensal (US$ 5,79/mês ou US$ 39,99/ano).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Quando o KoalaSync se ajusta melhor",
"ALT_SCENER_WHEN_KOALA_BODY": "O KoalaSync brilha quando se trata de <strong>qualidade, privacidade e simplicidade de vídeo</strong>:<br><br>• <strong>Sem contas</strong>: você não precisa se registrar, fazer login ou gerenciar perfis. Basta ativar a extensão, compartilhar um código de sala e começar a assistir.<br>• <strong>Qualidade nativa real (4K/HDR)</strong>: o Scener transmite vídeo compactado de um servidor virtual em nuvem, o que pode levar à perda de qualidade e atrasos. O KoalaSync sincroniza o player nativo diretamente no seu computador, o que significa que você assiste filmes na resolução total da sua assinatura de streaming.<br>• <strong>Baixo uso de largura de banda</strong>: como apenas dados de controle (reprodução, pausa, registros de data e hora) são transmitidos, o KoalaSync praticamente não usa largura de banda extra. O Scener transmite todos os feeds de vídeo e câmera por meio de servidores em nuvem, o que pode sobrecarregar muito conexões de Internet mais lentas e laptops mais antigos.<br>• <strong>100% gratuito e sem anúncios</strong>: sem taxas de assinatura mensal, sem anúncios e sem rastreadores.<br>• <strong>Arquivos de vídeo locais</strong>: como o KoalaSync é executado localmente, você pode até assistir seus próprios arquivos de vídeo (como MP4) em sincronia com amigos. Basta arrastar e soltar o arquivo em uma guia do navegador o Scener não pode fazer isso porque seu player roda na nuvem.",
"ALT_SCENER_MAIN_DIFF_TITLE": "A principal diferença",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener é uma <strong>rede social comercial</strong> para assistir festas que é alimentada por navegadores virtuais em nuvem e financiada por anúncios e assinaturas mensais. KoalaSync é um <strong>utilitário de sincronização gratuito e com foco na privacidade</strong> que se conecta diretamente às guias do seu navegador. Ele deixa o bate-papo por voz/vídeo para aplicativos como Discord ou Teamspeak, concentrando-se inteiramente em manter sua reprodução fluida, privada e em sua qualidade original nativa.",
"ALT_SCENER_LIMITS_TITLE": "Limitações honestas",
"ALT_SCENER_LIMITS_BODY": "KoalaSync <strong>não oferece suporte integrado para chat ou webcam</strong>. É puramente uma ferramenta de sincronização e requer uma ferramenta de chamada de voz separada de sua escolha. Além disso, o KoalaSync atualmente é apenas para desktop, e a compatibilidade do arquivo de vídeo local depende inteiramente se o seu navegador suporta nativamente a reprodução do formato de vídeo e codecs de áudio.",
"ALT_SCENER_SUMMARY_TITLE": "Resumidamente",
"ALT_SCENER_SUMMARY_BODY": "Para grandes grupos de observação com bate-papo na webcam integrado e recursos sociais, o Scener é a escolha certa, desde que você não se importe com anúncios e acessos pagos premium. Se você deseja uma experiência totalmente gratuita, sem anúncios e sem distrações no player nativo (incluindo Netflix, Prime Video, Disney+ ou arquivos de navegador local) e já está em uma chamada de voz, o KoalaSync é a solução mais limpa e com melhor desempenho.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: Qual alternativa de festa da Netflix se adapta melhor?",
"ALT_KOSMI_META_DESC": "Uma comparação honesta entre KoalaSync e Kosmi. Descubra por que a configuração sem extensão do Kosmi é conveniente e quando a qualidade de vídeo nativa do KoalaSync vence.",
"ALT_KOSMI_INTRO": "Tanto o KoalaSync quanto o Kosmi oferecem ótimas maneiras de assistir Netflix, YouTube e outras plataformas em sincronia com amigos. No entanto, as suas tecnologias subjacentes são fundamentalmente diferentes. Kosmi usa navegadores virtuais em nuvem que são executados diretamente em seu navegador sem instalar extensões. KoalaSync é uma extensão leve que sincroniza seu player de vídeo local. A abordagem mais adequada para você depende de suas prioridades em relação à qualidade, conveniência e privacidade do vídeo.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Quando Kosmi é a melhor escolha",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi é imbatível se você quiser <strong>evitar instalar qualquer coisa</strong> ou quiser assistir em dispositivos como tablets e smartphones. Como o Kosmi executa navegadores virtuais na nuvem, basta um simples link da web para ingressar. Além disso, Kosmi é uma plataforma de hangout completa: além do streaming sincronizado, você pode jogar jogos multijogador (como clássicos retrô do NES/SNES ou pôquer) e usar a webcam integrada, bate-papo por voz e texto. Se você quer uma noite de jogos sociais e assistir a uma festa sem configuração, Kosmi é uma solução fantástica.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Quando o KoalaSync se ajusta melhor",
"ALT_KOSMI_WHEN_KOALA_BODY": "O KoalaSync brilha quando se trata de <strong>qualidade de reprodução, segurança e desempenho nativos</strong>:<br><br>• <strong>Sem riscos de segurança</strong>: com o Kosmi, você precisa fazer login na sua conta Netflix ou Prime em um computador virtual remoto na nuvem. Com o KoalaSync, você faz login com segurança no site oficial de streaming em seu próprio navegador, como faria normalmente. Suas senhas nunca saem da sua máquina.<br>• <strong>Qualidade total de vídeo (4K/HDR)</strong>: o Kosmi transmite a tela do navegador virtual como um feed de vídeo compactado, o que pode resultar em pixelização e buffer. O KoalaSync sincroniza os players nativos localmente: você desfruta de filmes na resolução completa e nítida da sua assinatura.<br>• <strong>Sem atraso e compatível com largura de banda</strong>: como o KoalaSync envia apenas comandos de controle (reproduzir/pausar/carimbos de data/hora), ele usa quase zero largura de banda. Kosmi transmite constantemente feeds de vídeo em HD, o que pode sobrecarregar conexões mais lentas.<br>• <strong>Arquivos de vídeo locais</strong>: se quiser assistir a um vídeo privado, basta arrastar e soltar o arquivo MP4 em uma guia do navegador e sincronizá-lo. Kosmi não pode acessar arquivos em seu disco rígido local.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "A principal diferença",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi é um <strong>ponto de encontro virtual na nuvem</strong> que transmite a tela de um navegador remoto para que ninguém precise instalar uma extensão. KoalaSync é uma <strong>camada de sincronização local do navegador</strong> que se conecta diretamente ao player nativo no site oficial de streaming. Embora o Kosmi seja mais versátil para minijogos e compatibilidade de dispositivos, o KoalaSync oferece uma experiência de streaming mais segura, fluida e nítida no player original.",
"ALT_KOSMI_LIMITS_TITLE": "Limitações honestas",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>requer a instalação de uma extensão de navegador</strong> e atualmente só funciona em PCs desktop. Ele <strong>não possui bate-papo ou webcams integrados</strong>, pois foi projetado sob a suposição de que você já está conversando via Discord ou outras ferramentas de voz. Também não oferece jogos integrados.",
"ALT_KOSMI_SUMMARY_TITLE": "Resumidamente",
"ALT_KOSMI_SUMMARY_BODY": "Para noites de jogos casuais com clássicos retrô e fácil acesso em dispositivos móveis sem qualquer instalação, o Kosmi é ideal. Para noites de cinema premium no Netflix, Prime Video, Disney+ ou Plex em qualidade 4K total, com segurança máxima e impacto mínimo na largura de banda, o KoalaSync é o vencedor claro.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: Qual solução de watch party se adapta melhor?",
"ALT_TWOSEVEN_META_DESC": "Uma comparação honesta entre KoalaSync e TwoSeven. Descubra quando a webcam integrada do TwoSeven vence e por que o KoalaSync é melhor para Disney+ e Netflix.",
"ALT_TWOSEVEN_INTRO": "Tanto o KoalaSync quanto o TwoSeven usam a mesma abordagem básica para assistir grupos: eles sincronizam o player de vídeo original diretamente no seu navegador, em vez de transmitir um feed de vídeo compactado da nuvem. Isso garante qualidade de vídeo de alto nível para ambas as ferramentas. No entanto, embora o TwoSeven seja um portal comercial com chat de webcam integrado e níveis de assinatura, o KoalaSync continua sendo uma extensão minimalista, totalmente gratuita e com privacidade. Descubra aqui qual serviço se adapta melhor a você.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Quando TwoSeven é a melhor escolha",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven é a escolha certa se você deseja uma <strong>solução completa com webcam integrada e chat de áudio</strong> diretamente no seu navegador. Se você quiser ver seus amigos enquanto assiste sem precisar rodar o Discord ou Teamspeak em segundo plano, o TwoSeven oferece essa integração de forma nativa. Além disso, funciona para o YouTube e alguns players de vídeo da web abertos sem extensões. É adequado para pequenos grupos de 2 a 3 pessoas que desejam compartilhar uma conexão visual durante a visualização.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Quando o KoalaSync se ajusta melhor",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync brilha com sua <strong>total falta de taxas, privacidade e simplicidade</strong>:<br><br>• <strong>Sem paywalls</strong>: para assistir serviços premium como Disney+ ou Hulu sincronizados no TwoSeven, pelo menos um membro da sala deve apoiá-los no Patreon (a partir de US$ 3/mês). KoalaSync sincroniza Netflix, Prime Video, Disney+ e servidores de mídia auto-hospedados (Jellyfin, Plex, Emby) 100% grátis e sem restrições.<br>• <strong>Privacidade absoluta (sem rastreadores/anúncios)</strong>: TwoSeven é suportado por anúncios e usa vários rastreadores do Google, Facebook e outros. O KoalaSync não tem anúncios nem rastreadores e se comunica exclusivamente com o servidor de retransmissão somente RAM.<br>• <strong>Não é necessário registro</strong>: o TwoSeven exige que todos os participantes criem uma conta e façam login. O KoalaSync é totalmente gratuito. Basta instalar, inserir um código de sala e começar a assistir.<br>• <strong>Leve e com poucos recursos</strong>: a webcam integrada e os feeds de áudio do TwoSeven sobrecarregam sua CPU e sua rede. Ao deixar a comunicação para ferramentas como o Discord, o KoalaSync funciona de forma extremamente suave e preserva a vida útil da bateria.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "A principal diferença",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven é uma <strong>plataforma comercial</strong> com requisitos de registro, anúncios, chats peer-to-peer por webcam e paywalls do Patreon para serviços de streaming específicos. KoalaSync é um <strong>utilitário gratuito e de código aberto</strong> que se conecta diretamente às guias do seu navegador sem contas, rastreadores ou custos extras, permitindo assistir sem distrações no player nativo.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Limitações honestas",
"ALT_TWOSEVEN_LIMITS_BODY": "O KoalaSync <strong>não oferece webcam integrada ou bate-papo com áudio</strong> e pressupõe que você já esteja em uma chamada via Discord ou ferramenta semelhante. Além disso, o KoalaSync não possui sobreposição de caixa de bate-papo integrada e atualmente é apenas para desktop.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Resumidamente",
"ALT_TWOSEVEN_SUMMARY_BODY": "Para pequenos grupos de duas ou três pessoas que desejam se ver através de webcams diretamente no navegador e não se importam em apoiar um Patreon para suporte Disney +, TwoSeven é uma boa opção. Para noites de cinema privadas, totalmente gratuitas e sem anúncios em qualidade 4K nativa (seja Netflix, Prime Video, Disney+ ou Jellyfin) sem registros, o KoalaSync é a escolha mais limpa e segura.",
"ALT_TRY_KOALASYNC": "Experimente o KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Controlo do anfitrião",
"MOCK_HOST_CONTROL_TOGGLE": "Apenas eu posso controlar a reprodução",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync не заменяет голосовую связь. Если во время просмотра вы хотите общаться, используйте Discord, TeamSpeak, Signal, WhatsApp или любой другой привычный вам сервис.<br><br>Каждому участнику также необходим доступ к видео или веб-странице на собственном устройстве. KoalaSync не обходит требования к подписке, авторизации, DRM-защите, региональные ограничения или правила платформ.<br><br>На данный момент сервис работает только в браузерах на ПК, не имеет встроенного чата или функции голосовой связи, а совместимость зависит от конкретного браузера и видеоплеера.",
"ALT_SCREEN_SUMMARY_TITLE": "Краткий обзор",
"ALT_SCREEN_SUMMARY_BODY": "Демонстрация экрана — самый простой вариант, если нужно быстро всё организовать и вас не особо волнуют качество, конфиденциальность или возможность индивидуального управления. KoalaSync лучше подходит для ситуаций, когда каждый участник смотрит видео локально в своем браузере, а сам сеанс больше напоминает реальный совместный просмотр.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync против Watch2Gether: какое решение для часовых вечеринок подходит лучше?",
"ALT_W2G_META_DESC": "Честное сравнение KoalaSync и Watch2Gether. Узнайте, когда гибкость KoalaSync непревзойденна и почему Watch2Gether по-прежнему остается лучшим выбором для YouTube.",
"ALT_W2G_INTRO": "KoalaSync и Watch2Gether решают одну и ту же проблему: синхронизировать видео с друзьями в Интернете без координации вручную. В то время как Watch2Gether — один из старейших и самых популярных центров для совместных вечеров кино, KoalaSync использует совершенно другой, облегченный подход. Какой инструмент подойдет именно вам, во многом зависит от того, что и где вы хотите смотреть.",
"ALT_W2G_WHEN_W2G_TITLE": "Когда Watch2Gether — лучший выбор",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether непревзойденно подходит для <strong>вечеринок просмотра YouTube</strong>. Благодаря встроенному списку воспроизведения и поиску любой человек в комнате может легко находить, добавлять и воспроизводить новые видео. Все вместе без проблем смотрят следующее видео.<br><br>При использовании KoalaSync на YouTube автоматический запуск сайта по умолчанию включается, перенаправляя каждого пользователя на другое рекомендуемое видео. Наша функция автоматического перехода к следующему эпизоду («Лобби эпизода»), которая отлично работает на Netflix или Disney+, не работает на YouTube из-за этих динамических рекомендаций. Для вечеров, посвященных чистому YouTube, Watch2Gether — лучший выбор.",
"ALT_W2G_WHEN_KOALA_TITLE": "Когда KoalaSync подходит лучше",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync отлично работает на <strong>реальных потоковых сервисах</strong> (Netflix, Prime Video, Disney+) и автономных медиасерверах (Jellyfin, Plex, Emby). В отличие от Watch2Gether, который зачастую вообще не может воспроизводить премиум-контент, KoalaSync синхронизирует собственный проигрыватель непосредственно с веб-сайтом.<br><br>Он работает практически на любом сайте со стандартным видеоплеером HTML5. Вам не нужно настраивать виртуальную комнату на стороннем сайте: просто активируйте расширение, присоединитесь к лобби и начинайте просмотр.",
"ALT_W2G_MAIN_DIFF_TITLE": "Основное отличие",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether  это <strong>автономный веб-сайт</strong> со встроенным чатом, плейлистами и поддержкой веб-камеры. KoalaSync  это <strong>минималистичное расширение для браузера</strong>, которое подключается непосредственно к обычным вкладкам браузера.<br><br>Ищете универсальный пакет для YouTube со встроенным чатом? Используйте Watch2Gether. Хотите смотреть фильмы на Netflix или на своем собственном сервере, не отвлекаясь, в исходном качестве (без сжатия сервера)? KoalaSync — более чистое решение.",
"ALT_W2G_LIMITS_TITLE": "Честные ограничения",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>не имеет встроенных плейлистов и поиска видео</strong>. На YouTube это означает, что автоматическое воспроизведение следующего видео не будет синхронизироваться.<br><br>Кроме того, здесь <strong>нет встроенного чата</strong>, а KoalaSync в настоящее время работает только в браузерах для настольных компьютеров. Он разработан исходя из предположения, что вы в любом случае уже разговариваете через Discord, Teamspeak или другие голосовые инструменты.",
"ALT_W2G_SUMMARY_TITLE": "Суммируя",
"ALT_W2G_SUMMARY_BODY": "Watch2Gether — лучший выбор для спонтанных сеансов YouTube с плейлистами и встроенным чатом. Для платформ потокового вещания премиум-класса (таких как Netflix, Prime Video, Disney+), автономных серверов (Jellyfin, Plex, Emby) и максимальной гибкости браузера KoalaSync является более подходящим и легким инструментом.",
"ALT_SCENER_TITLE": "KoalaSync против Scener: какая платформа для часовых вечеринок подходит лучше?",
"ALT_SCENER_META_DESC": "Честное сравнение KoalaSync и Scener. Узнайте, когда чат с веб-камеры Scener побеждает и почему KoalaSync лучше всего подходит для вечерних кинопросмотров, не отвлекаясь.",
"ALT_SCENER_INTRO": "KoalaSync и Scener подходят к просмотру вечеринок с двух совершенно разных точек зрения. Scener — виртуальный кинотеатр со встроенным видеочатом и интерактивными комнатами. KoalaSync, с другой стороны, представляет собой минималистское расширение для браузера, обеспечивающее конфиденциальность, которое просто синхронизирует элементы управления воспроизведением. Какой инструмент подойдет вам лучше всего, зависит главным образом от того, насколько важны для вас встроенные функции веб-камеры и чата.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Когда Scener — лучший выбор",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener — хороший выбор, если вам нужна <strong>универсальная социальная платформа</strong> со встроенным видео- и аудиочатом прямо в вашем браузере. Scener создает виртуальную комнату, в которой веб-камеры игрока и ваших друзей отображаются рядом. Это идеально подходит для больших публичных вечеринок или виртуальных потоковых мероприятий, где социальный аспект находится на переднем плане. Однако имейте в виду, что бесплатная базовая версия поддерживаетс рекламой, а Scener блокирует многие функции (например, просмотр без рекламы и неограниченный видеочат) за ежемесячную подписку (5,79 долларов США в месяц или 39,99 долларов США в год).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Когда KoalaSync подходит лучше",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync превосходен, когда дело касается <strong>качества видео, конфиденциальности и простоты</strong>:<br><br>• <strong>Нет учетных записей</strong>: вам не нужно регистрироваться, входить в систему или управлять профилями. Просто активируйте расширение, поделитесь кодом комнаты и начинайте просмотр.<br>• <strong>Настоящее качество (4K/HDR)</strong>: Scener передает сжатое видео с виртуального облачного сервера, что может привести к потере качества и задержкам. KoalaSync синхронизирует встроенный проигрыватель непосредственно на вашем компьютере, что означает, что вы смотрите фильмы в полном разрешении, предусмотренном вашей подпиской на потоковую передачу.<br>• <strong>Низкое использование полосы пропускания</strong>: поскольку передаются только управляющие данные (воспроизведение, пауза, временные метки), KoalaSync практически не использует дополнительную полосу пропускания. Scener передает все видео и видео с камер через облачные серверы, что может сильно нагружать медленные интернет-соединения и стрые ноутбуки.<br>• <strong>100 % бесплатно и без рекламы</strong>: без ежемесячной абонентской платы, без рекламы и трекеров.<br>• <strong>Локальные видеофайлы</strong>: поскольку KoalaSync работает локально, вы даже можете смотреть свои собственные видеофайлы (например, MP4) синхронно с друзьями. Просто перетащите файл на вкладку браузера — Scener не может этого сделать, поскольку его плеер работает в облаке.",
"ALT_SCENER_MAIN_DIFF_TITLE": "Основное отличие",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener  это <strong>коммерческая социальная сеть</strong> для вечеринок, работающая на базе виртуальных облачных браузеров и финансируемая за счет рекламы и ежемесячных подписок. KoalaSync  это <strong>бесплатная утилита синхронизации, обеспечивающая конфиденциальность</strong>, которая подключается непосредственно к вкладкам вашего браузера. Он оставляет голосовой/видеочат таким приложениям, как Discord или Teamspeak, полностью сосредотачиваясь на обеспечении плавного, конфиденциального и исходного качества воспроизведения.",
"ALT_SCENER_LIMITS_TITLE": "Честные ограничения",
"ALT_SCENER_LIMITS_BODY": "KoalaSync не предлагает <strong>отсутствие встроенной поддержки чата или веб-камеры</strong>. Это чисто инструмент синхронизации, для которого требуется отдельный инструмент голосового вызова по вашему выбору. Кроме того, KoalaSync в настоящее время доступен только для настольных компьютеров, а совместимость локальных видеофайлов полностью зависит от того, поддерживает ли ваш браузер изначально воспроизведение видеоформата и аудиокодеков.",
"ALT_SCENER_SUMMARY_TITLE": "Суммируя",
"ALT_SCENER_SUMMARY_BODY": "Для больших вечеринок просмотра со встроенным чатом через веб-камеру и социальными функциями Scener — правильный выбор, при условии, что вы не возражаете против рекламы и платного доступа премиум-класса. Если вам нужна совершенно бесплатная работа без рекламы и отвлекающих факторов в родном плеере (включая файлы Netflix, Prime Video, Disney+ или локального браузера), и вы уже участвуете в голосовом вызове, KoalaSync — более чистое и производительное решение.",
"ALT_KOSMI_TITLE": "KoalaSync против Kosmi: какая альтернатива вечеринке Netflix подходит лучше?",
"ALT_KOSMI_META_DESC": "Честное сравнение KoalaSync и Kosmi. Узнайте, почему настройка Kosmi без расширений удобна и когда преимущество имеет собственное качество видео KoalaSync.",
"ALT_KOSMI_INTRO": "И KoalaSync, и Kosmi предлагают отличные способы синхронного просмотра Netflix, YouTube и других платформ с друзьями. Однако их базовые технологии принципиально различны. Kosmi использует виртуальные облачные браузеры, которые запускаются прямо в вашем веб-браузере без установки расширений. KoalaSync — это легкое расширение, которое синхронизирует ваш локальный видеоплеер. Какой подход подойдет вам лучше всего, зависит от ваших приоритетов в отношении качества видео, удобства и конфиденциальности.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Когда Косми — лучший выбор",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi непобедим, если вы хотите <strong>не устанавливать что-либо</strong> или хотите смотреть на таких устройствах, как планшеты и смартфоны. Поскольку Kosmi использует виртуальные браузеры в облаке, все, что нужно для присоединения, — это простая веб-ссылка. Кроме того, Kosmi — это универсальная платформа для видеовстреч: помимо синхронизированной потоковой передачи вы можете играть в многопользовательские игры (например, в ретро-классику для NES/SNES или в покер) и использовать встроенную веб-камеру, голосовой и текстовый чат. Если вы хотите провести вечер социальных игр и посмотреть вечеринку без предварительной настройки, Kosmi — фантастическое решение.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Когда KoalaSync подходит лучше",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync превосходен, когда дело касается <strong>собственного качества воспроизведения, безопасности и производительности</strong>:<br><br>• <strong>Нет угроз безопасности</strong>: с Kosmi вам необходимо войти в свою учетную запись Netflix или Prime на удаленном виртуальном компьютере в облаке. С KoalaSync вы безопасно входите на официальный сайт потокового вещания в своем браузере, как обычно. Ваши пароли никогда не покидают ваш компьютер.<br>• <strong>Полное качество видео (4K/HDR)</strong>: Kosmi транслирует экран виртуального браузера в виде сжатого видеопотока, что может привести к пикселизации и буферизации. KoalaSync локально синхронизирует встроенные проигрыватели: вы наслаждаетесь фильмами в полном кристально чистом разрешении, предусмотренном вашей подпиской.<br>• <strong>Без задержек и оптимальное использование пропускной способности</strong>: поскольку KoalaSync отправляет только команды управления (воспроизведение/пауза/временные метки), он использует практически нулевую полосу пропускания. Kosmi постоянно транслирует видео высокой четкости, что может затруднить медленное соединение.<br>• <strong>Локальные видеофайлы</strong>. Если вы хотите посмотреть личное видео, просто перетащите файл MP4 на вкладку браузера и синхронизируйте его. Kosmi не может получить доступ к файлам на вашем локальном жестком диске.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "Основное отличие",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi  это <strong>виртуальная облачная тусовка</strong>, которая транслирует экран удаленного браузера, поэтому никому не придется устанавливать расширение. KoalaSync  это <strong>уровень синхронизации с локальным браузером</strong>, который подключается непосредственно к встроенному плееру на официальном сайте потокового вещания. В то время как Kosmi более универсален для мини-игр и совместимости с устройствами, KoalaSync предлагает более безопасный, плавный и четкий процесс потоковой передачи в исходном проигрывателе.",
"ALT_KOSMI_LIMITS_TITLE": "Честные ограничения",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>требует установки расширения для браузера</strong> и в настоящее время работает только на настольных ПК. Он <strong>не имеет встроенного чата или веб-камеры</strong>, поскольку он разработан с учетом того, что вы все равно уже разговариваете через Discord или другие голосовые инструменты. Он также не предлагает встроенных игр.",
"ALT_KOSMI_SUMMARY_TITLE": "Суммируя",
"ALT_KOSMI_SUMMARY_BODY": "Kosmi идеально подходит для вечерних казуальных игр с классическими ретро-играми и легким доступом на мобильных устройствах без какой-либо установки. KoalaSync — явный победитель для вечерних фильмов премиум-класса на Netflix, Prime Video, Disney+ или Plex в полном качестве 4K, с максимальной безопасностью и минимальным воздействием на полосу пропускания.",
"ALT_TWOSEVEN_TITLE": "KoalaSync против TwoSeven: какое решение для вечеринок подходит лучше?",
"ALT_TWOSEVEN_META_DESC": "Честное сравнение KoalaSync и TwoSeven. Узнайте, когда побеждает встроенная веб-камера TwoSeven и почему KoalaSync лучше всего подходит для Disney+ и Netflix.",
"ALT_TWOSEVEN_INTRO": "И KoalaSync, и TwoSeven используют один и тот же базовый подход для вечеринок просмотра: они синхронизируют исходный видеоплеер непосредственно в вашем браузере, а не передают потоковое сжатое видео из облака. Это обеспечивает высочайшее качество видео для обоих инструментов. Однако, хотя TwoSeven — это коммерческий портал со встроенным чатом с веб-камерой и уровнями подписки, KoalaSync остается минималистичным, совершенно бесплатным и безопасным для конфиденциальности расширением. Узнайте, какая услуга подходит вам лучше всего здесь.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Когда TwoSeven — лучший выбор",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven — правильный выбор, если вам нужно <strong>комплексное решение со встроенной веб-камерой и аудиочатом</strong> прямо в браузере. Если вы хотите видеть своих друзей во время просмотра без необходимости запуска Discord или Teamspeak в фоновом режиме, TwoSeven предлагает эту интеграцию изначально. Кроме того, он работает для YouTube и некоторых открытых веб-видеоплееров без расширений. Он хорошо подходит для небольших групп из 2–3 человек, которые хотят поделиться визуальным впечатлением во время просмотра.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Когда KoalaSync подходит лучше",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync блистает своим <strong>полным отсутствием комиссий, конфиденциальностью и простотой</strong>:<br><br>• <strong>Нет платного доступа</strong>: чтобы синхронизировать премиум-сервисы, такие как Disney+ или Hulu, на TwoSeven, хотя бы один участник комнаты должен поддерживать их на Patreon (от 3 долларов США в месяц). KoalaSync синхронизирует Netflix, Prime Video, Disney+ и локальные медиа-серверы (Jellyfin, Plex, Emby) на 100 % бесплатно и без ограничений.<br>• <strong>Абсолютная конфиденциальность (без трекеров и рекламы)</strong>: TwoSeven поддерживается рекламой и использует несколько трекеров от Google, Facebook и других. В KoalaSync нет рекламы и трекеров, и он взаимодействует исключительно с сервером ретрансляции, работающим только в оперативной памяти.<br>• <strong>Регистрация не требуется</strong>: TwoSeven требует, чтобы все участники создали учетную запись и вошли в систему. KoalaSync полностью не требует учетной записи. Просто установите, введите код комнаты и начинайте просмотр.<br>• <strong>Легкость и экономичность</strong>. Встроенная веб-камера и аудиоканалы TwoSeven создают большую нагрузку на ваш процессор и сеть. Оставляя связь таким инструментам, как Discord, KoalaSync работает очень плавно и экономит заряд батареи.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "Основное отличие",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven  это <strong>коммерческая платформа</strong> с требованиями к регистрации, рекламой, одноранговыми чатами через веб-камеру и платным доступом Patreon для определенных потоковых сервисов. KoalaSync  это <strong>бесплатная утилита с открытым исходным кодом</strong>, которая подключается непосредственно к вкладкам вашего браузера без использования учетных записей, трекеров и дополнительных затрат, что позволяет смотреть видео в родном проигрывателе, не отвлекаясь.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Честные ограничения",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync не предлагает <strong>нет встроенной веб-камеры или аудиочата</strong> и предполагает, что вы уже разговариваете по телефону через Discord или аналогичный инструмент. Кроме того, KoalaSync не имеет встроенного окна чата и в настоящее время доступен только для настольных компьютеров.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Суммируя",
"ALT_TWOSEVEN_SUMMARY_BODY": "TwoSeven — хороший вариант для небольших групп из двух или трех человек, которые хотят видеть друг друга через веб-камеры прямо в браузере и не против поддержать Patreon для поддержки Disney+. KoalaSync — более чистый и безопасный выбор для без рекламы, совершенно бесплатно и приватных вечеров просмотра фильмов в собственном качестве 4K (будь то Netflix, Prime Video, Disney+ или Jellyfin) без регистрации.",
"ALT_TRY_KOALASYNC": "Попробовать KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Управление ведущим",
"MOCK_HOST_CONTROL_TOGGLE": "Только я могу управлять воспроизведением",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync, sesli görüşmenin yerini tutmaz. İzleme sırasında konuşmak isterseniz, yine Discord, Teamspeak, Signal, WhatsApp veya normalde kullandığınız herhangi bir aracı kullanmaya devam edebilirsiniz.<br><br>Ayrıca herkesin ilgili videoya veya sayfaya kendi cihazından erişebilmesi gerekir. KoalaSync; abonelikleri, oturum açma işlemlerini, DRM korumalarını, bölgesel kısıtlamaları veya platform kurallarını devre dışı bırakmaz.<br><br>Şu anda yalnızca masaüstü tarayıcılarında çalışır; yerleşik bir sohbet veya sesli görüşme özelliği yoktur ve uyumluluk her zaman kullanılan tarayıcıya ve video oynatıcıya bağlıdır.",
"ALT_SCREEN_SUMMARY_TITLE": "Özet",
"ALT_SCREEN_SUMMARY_BODY": "Hızlı bir çözüm aradığınızda ve kalite, gizlilik ya da bireysel kontrol konularına çok önem vermediğinizde, ekran paylaşımı en basit seçenektir. Herkesin içeriği kendi tarayıcısında yerel olarak izlemesi gereken ve oturumun gerçekten birlikte izliyormuş hissi verdiği durumlarda ise KoalaSync daha uygun bir tercihtir.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Hangi parti izleme çözümü daha uygun?",
"ALT_W2G_META_DESC": "KoalaSync ve Watch2Gether arasında dürüst bir karşılaştırma. KoalaSync'in esnekliğinin ne zaman rakipsiz olduğunu ve Watch2Gether'in neden hâlâ YouTube için en iyi seçenek olduğunu keşfedin.",
"ALT_W2G_INTRO": "KoalaSync ve Watch2Gether aynı sorunu çözüyor: Videoları manuel olarak koordine etmeden çevrimiçi olarak arkadaşlarınızla senkronize olarak izlemek. Watch2Gether, paylaşımlı film geceleri için en eski ve en popüler merkezlerden biri olsa da KoalaSync tamamen farklı ve hafif bir yaklaşım benimsiyor. Hangi aracın sizin için uygun olduğu büyük ölçüde neyi ve nerede izlemek istediğinize bağlıdır.",
"ALT_W2G_WHEN_W2G_TITLE": "Watch2Gether ne zaman daha iyi bir seçimdir",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether, <strong>YouTube izleme partileri</strong> için rakipsizdir. Yerleşik oynatma listesi ve arama özelliği sayesinde odadaki herkes yeni videoları kolayca bulabilir, ekleyebilir ve oynatabilir. Herkes bir sonraki videoyu sorunsuz bir şekilde birlikte izler.<br><br>YouTube'daki KoalaSync ile sitenin varsayılan otomatik oynatma özelliği devreye girerek her kullanıcıyı farklı bir önerilen videoya yönlendirir. Netflix veya Disney+'ta harika çalışan otomatik sonraki bölüm özelliğimiz (\"Bölüm Lobisi\"), bu dinamik öneriler nedeniyle YouTube'da çalışmıyor. Saf YouTube geceleri için Watch2Gether daha iyi bir seçimdir.",
"ALT_W2G_WHEN_KOALA_TITLE": "KoalaSync daha iyi uyduğunda",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync, <strong>gerçek yayın hizmetlerinde</strong> (Netflix, Prime Video, Disney+) ve kendi kendine barındırılan medya sunucularında (Jellyfin, Plex, Emby) öne çıkıyor. Premium içeriği çoğu zaman oynatamayan Watch2Gether'den farklı olarak KoalaSync, yerel oynatıcıyı doğrudan web sitesinde senkronize eder.<br><br>Standart HTML5 video oynatıcısı olan hemen hemen her sitede çalışır. Üçüncü taraf bir sitede sanal oda oluşturmanıza gerek yoktur: uzantıyı etkinleştirmeniz, bir lobiye katılmanız ve izlemeye başlamanız yeterlidir.",
"ALT_W2G_MAIN_DIFF_TITLE": "Temel fark",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether, yerleşik sohbet, çalma listeleri ve web kamerası desteğine sahip <strong>bağımsız bir web sitesidir</strong>. KoalaSync, doğrudan normal tarayıcı sekmelerinize bağlanan <strong>minimalist bir tarayıcı uzantısıdır</strong>.<br><br>Yerleşik sohbet içeren, YouTube için hepsi bir arada bir paket mi arıyorsunuz? Watch2Gether'ı kullanın. Netflix'te veya kendi sunucunuzda, dikkatiniz dağılmadan, yerel kalitede (sunucu sıkıştırması olmadan) film izlemek ister misiniz? KoalaSync daha temiz bir çözümdür.",
"ALT_W2G_LIMITS_TITLE": "Dürüst sınırlamalar",
"ALT_W2G_LIMITS_BODY": "KoalaSync'in <strong>yerleşik oynatma listeleri veya video araması yoktur</strong>. YouTube'da bu, bir sonraki videonun otomatik olarak oynatılmasının senkronize kalmayacağı anlamına gelir.<br><br>Ayrıca, <strong>yerleşik sohbet yoktur</strong> ve KoalaSync şu anda yalnızca masaüstü tarayıcılarda çalışmaktadır. Zaten Discord, Teamspeak veya diğer ses araçları aracılığıyla konuştuğunuz varsayımıyla tasarlanmıştır.",
"ALT_W2G_SUMMARY_TITLE": "Kısacası",
"ALT_W2G_SUMMARY_BODY": "Oynatma listeleri ve yerleşik sohbet içeren spontane YouTube oturumları için Watch2Gether en iyi seçimdir. Birinci sınıf yayın platformları (Netflix, Prime Video, Disney+ gibi), kendi kendine barındırılan sunucular (Jellyfin, Plex, Emby) ve maksimum tarayıcı esnekliği için KoalaSync daha uygun ve hafif bir araçtır.",
"ALT_SCENER_TITLE": "KoalaSync vs Scener: Hangi izleme partisi platformu daha iyi uyuyor?",
"ALT_SCENER_META_DESC": "KoalaSync ve Scener'ın dürüst bir karşılaştırması. Scener'ın web kamerası sohbetinin ne zaman kazandığını ve KoalaSync'in dikkat dağıtıcı olmayan film geceleri için neden en iyisi olduğunu keşfedin.",
"ALT_SCENER_INTRO": "KoalaSync ve Scener partileri izlemeye tamamen farklı iki açıdan yaklaşıyor. Scener, yerleşik görüntülü sohbet ve etkileşimli odalara sahip sanal bir sinema salonudur. Öte yandan KoalaSync, oynatma kontrollerini kolayca senkronize eden minimalist, gizlilik dostu bir tarayıcı uzantısıdır. Hangi aracın size en uygun olduğu çoğunlukla yerleşik web kamerası ve sohbet özelliklerinin sizin için ne kadar önemli olduğuna bağlıdır.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Scener daha iyi bir seçim olduğunda",
"ALT_SCENER_WHEN_SCENER_BODY": "Doğrudan tarayıcınızda yerleşik görüntülü ve sesli sohbet içeren <strong>hepsi bir arada bir sosyal platform</strong> istiyorsanız Scener iyi bir seçimdir. Scener, oynatıcının ve arkadaşlarınızın web kameralarının yan yana görüntülendiği sanal bir oda oluşturur. Bu, sosyal yönün ön planda olduğu, halka açık büyük izleme partileri veya sanal yayın etkinlikleri için idealdir. Ancak, ücretsiz temel sürümün reklam destekli olduğunu ve Scener'ın birçok özelliği (reklamsız görüntüleme ve sınırsız görüntülü sohbet gibi) aylık bir aboneliğin (aylık 5,79 ABD doları veya yıllık 39,99 ABD doları) arkasında kilitlediğini unutmayın.",
"ALT_SCENER_WHEN_KOALA_TITLE": "KoalaSync daha iyi uyduğunda",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync, <strong>video kalitesi, gizlilik ve basitlik</strong> söz konusu olduğunda öne çıkıyor:<br><br>• <strong>Hesap yok</strong>: Kaydolmanıza, giriş yapmanıza veya profilleri yönetmenize gerek yok. Uzantıyı etkinleştirin, oda kodunu paylaşın ve izlemeye başlayın.<br>• <strong>Gerçek yerel kalite (4K/HDR)</strong>: Scener, sıkıştırılmış videoyu sanal bir bulut sunucusundan yayınlar; bu da kalite kaybına ve gecikmeye neden olabilir. KoalaSync, yerel oynatıcıyı doğrudan bilgisayarınızda senkronize eder; bu, filmleri akış aboneliğinizin tam çözünürlüğünde izleyebileceğiniz anlamına gelir.<br>• <strong>Düşük bant genişliği kullanımı</strong>: Yalnızca kontrol verileri (oynatma, duraklatma, zaman damgaları) iletildiğinden, KoalaSync neredeyse hiç ekstra bant genişliği kullanmaz. Scener, videonun tamamını ve kamera yayınlarını bulut sunucuları üzerinden yayınlar; bu da daha yavaş internet bağlantılarını ve eski dizüstü bilgisayarları büyük ölçüde zorlayabilir.<br>• <strong>%100 ücretsiz ve reklamsız</strong>: Aylık abonelik ücreti yok, reklam yok ve izleyici yok.<br>• <strong>Yerel video dosyaları</strong>: KoalaSync yerel olarak çalıştığından, kendi video dosyalarınızı (MP4 gibi) arkadaşlarınızla senkronize olarak bile izleyebilirsiniz. Dosyayı bir tarayıcı sekmesine sürükleyip bırakmanız yeterlidir; Scener, oynatıcısı bulutta çalıştığı için bunu yapamaz.",
"ALT_SCENER_MAIN_DIFF_TITLE": "Temel fark",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener, izleme partilerine yönelik, sanal bulut tarayıcıları tarafından desteklenen ve reklamlar ve aylık abonelikler aracılığıyla finanse edilen <strong>ticari bir sosyal ağdır</strong>. KoalaSync, doğrudan tarayıcı sekmelerinize bağlanan <strong>gizlilik öncelikli, ücretsiz bir senkronizasyon aracıdır</strong>. Sesli/görüntülü sohbeti Discord veya Teamspeak gibi uygulamalara bırakarak tamamen oynatmanızı akıcı, özel ve orijinal kalitesinde tutmaya odaklanır.",
"ALT_SCENER_LIMITS_TITLE": "Dürüst sınırlamalar",
"ALT_SCENER_LIMITS_BODY": "KoalaSync, <strong>yerleşik sohbet veya web kamerası desteği sunmaz</strong>. Tamamen bir senkronizasyon aracıdır ve seçeceğiniz ayrı bir sesli arama aracı gerektirir. Ek olarak, KoalaSync şu anda yalnızca masaüstünde mevcuttur ve yerel video dosyası uyumluluğu tamamen tarayıcınızın yerel olarak video formatını ve ses codec bileşenlerini oynatmayı destekleyip desteklemediğine bağlıdır.",
"ALT_SCENER_SUMMARY_TITLE": "Kısacası",
"ALT_SCENER_SUMMARY_BODY": "Yerleşik web kamerası sohbeti ve sosyal özelliklere sahip büyük izleme partileri için, reklamlara ve premium ödeme duvarlarına aldırış etmediğiniz sürece Scener doğru seçimdir. Yerel oynatıcıda (Netflix, Prime Video, Disney+ veya yerel tarayıcı dosyaları dahil) tamamen ücretsiz, reklamsız ve dikkat dağıtıcı olmayan bir deneyim istiyorsanız ve zaten sesli aramadaysanız, KoalaSync daha temiz ve daha performanslı bir çözümdür.",
"ALT_KOSMI_TITLE": "KoalaSync vs Kosmi: Hangi Netflix parti alternatifi daha iyi uyuyor?",
"ALT_KOSMI_META_DESC": "KoalaSync ve Kosmi'nin dürüst bir karşılaştırması. Kosmi'nin uzantısız kurulumunun neden kullanışlı olduğunu ve KoalaSync'in yerel video kalitesinin ne zaman kazandığını keşfedin.",
"ALT_KOSMI_INTRO": "Hem KoalaSync hem de Kosmi, Netflix, YouTube ve diğer platformları arkadaşlarınızla senkronize izlemenin harika yollarını sunuyor. Ancak bunların temelinde yatan teknolojiler temelde farklıdır. Kosmi, uzantı yüklemeden doğrudan web tarayıcınızda çalışan sanal bulut tarayıcılarını kullanır. KoalaSync, yerel video oynatıcınızı senkronize eden hafif bir uzantıdır. Hangi yaklaşımın size en uygun olduğu video kalitesi, kolaylık ve gizlilik konusundaki önceliklerinize bağlıdır.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Kosmi daha iyi bir seçim olduğunda",
"ALT_KOSMI_WHEN_KOSMI_BODY": "<strong>Herhangi bir şey yüklemekten kaçınmak</strong> veya tablet ve akıllı telefon gibi cihazlarda izlemek istiyorsanız Kosmi rakipsizdir. Kosmi bulutta sanal tarayıcılar çalıştırdığından katılmak için tek gereken basit bir web bağlantısıdır. Dahası, Kosmi hepsi bir arada bir hangout platformudur: senkronize akışa ek olarak, çok oyunculu oyunlar (retro NES/SNES klasikleri veya poker gibi) oynayabilir ve yerleşik web kamerasını, sesli ve yazılı sohbeti kullanabilirsiniz. Sosyal bir oyun gecesi istiyorsanız ve kurulum yapmadan parti izlemek istiyorsanız Kosmi harika bir çözüm.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "KoalaSync daha iyi uyduğunda",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync, <strong>yerel oynatma kalitesi, güvenlik ve performans</strong> söz konusu olduğunda parlıyor:<br><br>• <strong>Güvenlik riski yok</strong>: Kosmi ile buluttaki uzak bir sanal bilgisayar üzerinden Netflix veya Prime hesabınıza giriş yapmanız gerekir. KoalaSync ile normalde yaptığınız gibi resmi yayın web sitesinde kendi tarayıcınızda güvenli bir şekilde oturum açarsınız. Şifreleriniz makinenizden asla ayrılmaz.<br>• <strong>Tam video kalitesi (4K/HDR)</strong>: Kosmi, sanal tarayıcının ekranını sıkıştırılmış bir video akışı olarak yayınlar; bu da pikselleşmeye ve arabelleğe almaya neden olabilir. KoalaSync yerel oynatıcıları yerel olarak senkronize eder: filmlerin keyfini aboneliğinizin tam, kristal netliğinde çözünürlüğünde çıkarırsınız.<br>• <strong>Gecikmesiz ve bant genişliği dostu</strong>: KoalaSync yalnızca kontrol komutları (oynat/duraklat/zaman damgaları) gönderdiğinden, neredeyse sıfır bant genişliği kullanır. Kosmi sürekli olarak HD video akışları yayınlar, bu da daha yavaş bağlantıları bunaltabilir.<br>• <strong>Yerel video dosyaları</strong>: Özel bir video izlemek istiyorsanız MP4 dosyasını bir tarayıcı sekmesine sürükleyip bırakın ve senkronize edin. Kosmi, yerel sabit sürücünüzdeki dosyalara erişemiyor.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "Temel fark",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi, kimsenin bir uzantı yüklemesine gerek kalmaması için uzaktaki bir tarayıcının ekranına akış sağlayan bir <strong>sanal bulut hangout'udur</strong>. KoalaSync, resmi yayın web sitesindeki yerel oynatıcıya doğrudan bağlanan <strong>yerel bir tarayıcı senkronizasyon katmanıdır</strong>. Kosmi, mini oyunlar ve cihaz uyumluluğu açısından daha çok yönlü olsa da KoalaSync, orijinal oynatıcıda daha güvenli, akıcı ve keskin bir yayın deneyimi sunuyor.",
"ALT_KOSMI_LIMITS_TITLE": "Dürüst sınırlamalar",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>bir tarayıcı uzantısının yüklenmesini gerektirir</strong> ve şu anda yalnızca masaüstü bilgisayarlarda çalışmaktadır. Zaten Discord veya diğer ses araçları aracılığıyla konuştuğunuz varsayımıyla tasarlandığından <strong>yerleşik sohbet veya web kamerası yoktur</strong>. Ayrıca yerleşik oyunlar da sunmuyor.",
"ALT_KOSMI_SUMMARY_TITLE": "Kısacası",
"ALT_KOSMI_SUMMARY_BODY": "Retro klasiklerin yer aldığı gündelik oyun geceleri ve herhangi bir kurulum gerektirmeden mobil cihazlardan kolay erişim için Kosmi idealdir. Netflix, Prime Video, Disney+ veya Plex'te tam 4K kalitesinde, maksimum güvenlik ve minimum bant genişliği etkisi ile premium film geceleri için KoalaSync açık ara kazanandır.",
"ALT_TWOSEVEN_TITLE": "KoalaSync vs TwoSeven: Hangi parti izleme çözümü daha uygun?",
"ALT_TWOSEVEN_META_DESC": "KoalaSync ve TwoSeven'ın dürüst bir karşılaştırması. TwoSeven'ın yerleşik web kamerasının ne zaman kazandığını ve KoalaSync'in neden Disney+ ve Netflix için en iyisi olduğunu keşfedin.",
"ALT_TWOSEVEN_INTRO": "Hem KoalaSync hem de TwoSeven, izleme partileri için aynı temel yaklaşımı kullanıyor: buluttan sıkıştırılmış bir video yayını yayınlamak yerine, orijinal video oynatıcıyı doğrudan tarayıcınızda senkronize ediyorlar. Bu, her iki araç için de en üst düzey video kalitesini sağlar. Ancak TwoSeven yerleşik web kamerası sohbeti ve abonelik katmanlarına sahip ticari bir portal olmasına rağmen KoalaSync minimalist, tamamen ücretsiz ve gizlilik dostu bir uzantı olmaya devam ediyor. Hangi hizmetin size en uygun olduğunu buradan öğrenin.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "TwoSeven daha iyi bir seçim olduğunda",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "Doğrudan tarayıcınızda <strong>entegre web kamerası ve sesli sohbet içeren hepsi bir arada çözüm</strong> istiyorsanız TwoSeven doğru seçimdir. Arka planda Discord veya Teamspeak çalıştırmanıza gerek kalmadan izlerken arkadaşlarınızı görmek istiyorsanız TwoSeven bu entegrasyonu yerel olarak sunuyor. Ek olarak, YouTube ve uzantıları olmayan birkaç açık web video oynatıcısı için de çalışır. Görüntülerken görsel bir bağlantı paylaşmak isteyen 2 ila 3 kişilik küçük gruplar için çok uygundur.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "KoalaSync daha iyi uyduğunda",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync, <strong>hiçbir ücret, gizlilik ve basitlik eksikliği</strong> ile parlıyor:<br><br>• <strong>Ödeme duvarı yok</strong>: Disney+ veya Hulu gibi premium hizmetleri TwoSeven'da senkronize olarak izlemek için en az bir oda üyesinin bunları Patreon'da desteklemesi gerekir (ayda 3 ABD dolarından başlayan fiyatlarla). KoalaSync, Netflix, Prime Video, Disney+ ve kendi kendine barındırılan medya sunucularını (Jellyfin, Plex, Emby) sıfır kısıtlamayla %100 ücretsiz olarak senkronize eder.<br>• <strong>Mutlak gizlilik (izleyici/reklam yok)</strong>: TwoSeven reklam desteklidir ve Google, Facebook ve diğerlerinden birden fazla izleyici kullanır. KoalaSync'te reklam yoktur, izleyici yoktur ve yalnızca RAM geçiş sunucusuyla iletişim kurar.<br>• <strong>Kayıt gerekmez</strong>: TwoSeven, tüm katılımcıların bir hesap oluşturmasını ve oturum açmasını gerektirir. KoalaSync tamamen hesap gerektirmez. Sadece yükleyin, oda kodunu girin ve izlemeye başlayın.<br>• <strong>Hafif ve kaynak dostu</strong>: TwoSeven'in entegre web kamerası ve ses beslemeleri, CPU'nuza ve ağınıza ağır bir yük getirir. KoalaSync, iletişimi Discord gibi araçlara bırakarak son derece sorunsuz çalışır ve pil ömrünü korur.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "Temel fark",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven, kayıt gereklilikleri, reklamlar, eşler arası web kamerası sohbetleri ve belirli yayın hizmetleri için Patreon ödeme duvarları içeren <strong>ticari bir platformdur</strong>. KoalaSync, hesaplar, izleyiciler veya ekstra maliyetler olmadan doğrudan tarayıcı sekmelerinize bağlanan ve yerel oynatıcıda dikkatiniz dağılmadan izlemenize olanak tanıyan <strong>ücretsiz, açık kaynaklı bir yardımcı programdır</strong>.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Dürüst sınırlamalar",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync, <strong>yerleşik bir web kamerası veya sesli sohbet sunmaz</strong> ve Discord veya benzer bir araç aracılığıyla zaten bir görüşme yaptığınızı varsayar. Ek olarak, KoalaSync'in yerleşik bir sohbet kutusu arayüzü yoktur ve şu anda yalnızca masaüstünde mevcuttur.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Kısacası",
"ALT_TWOSEVEN_SUMMARY_BODY": "Web kameraları aracılığıyla birbirlerini doğrudan tarayıcıda görmek isteyen ve Disney+ için Patreon desteğini desteklemeyi dert etmeyen iki veya üç kişiden oluşan küçük gruplar için TwoSeven güzel bir seçenektir. Kayıt olmadan, reklamsız, tamamen ücretsiz ve yerel 4K kalitesinde (Netflix, Prime Video, Disney+ veya Jellyfin) özel film geceleri için KoalaSync daha temiz ve daha güvenli bir seçimdir.",
"ALT_TRY_KOALASYNC": "KoalaSync'i Deneyin",
"MOCK_HOST_CONTROL_LABEL": "Sunucu Kontrolü",
"MOCK_HOST_CONTROL_TOGGLE": "Oynatmayı yalnızca ben kontrol edebilirim",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync не замінює голосовий дзвінок. Якщо ви хочете розмовляти під час перегляду, ви все одно використовуєте Discord, Teamspeak, Signal, WhatsApp або будь-який інший додаток, який ви зазвичай використовуєте.<br><br>Кожному також потрібен доступ до відео або сторінки на власному пристрої. KoalaSync не обходить підписки, вхід, DRM, регіональні обмеження чи правила платформи.<br><br>Наразі він доступний лише для браузера на комп'ютері, не має вбудованої функції чату чи голосового зв'язку, а сумісність завжди залежить від браузера та відеоплеєра.",
"ALT_SCREEN_SUMMARY_TITLE": "Підсумок",
"ALT_SCREEN_SUMMARY_BODY": "Спільний доступ до екрана – це найпростіший варіант, коли ви просто хочете чогось швидкого і не дуже переймаєтеся якістю, конфіденційністю чи індивідуальним контролем. KoalaSync краще підходить, коли кожен має дивитися локально у своєму власному браузері, і сеанс має більше нагадувати спільний перегляд.",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync проти Watch2Gether: яке рішення для перегляду вечірок краще підходить?",
"ALT_W2G_META_DESC": "Чесне порівняння між KoalaSync і Watch2Gether. Дізнайтеся, коли гнучкість KoalaSync є неперевершеною та чому Watch2Gether досі залишається найкращим вибором для YouTube.",
"ALT_W2G_INTRO": "KoalaSync і Watch2Gether вирішують ту саму проблему: синхронізований перегляд відео з друзями онлайн без ручної координації. У той час як Watch2Gether є одним із найстаріших і найпопулярніших центрів для спільних кіновечорів, KoalaSync має зовсім інший, легкий підхід. Який інструмент підійде саме вам, залежить від того, що та де ви хочете дивитися.",
"ALT_W2G_WHEN_W2G_TITLE": "Коли Watch2Gether є кращим вибором",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether неперевершений для <strong>вечірок перегляду на YouTube</strong>. Завдяки вбудованому списку відтворення та пошуку будь-хто в кімнаті може легко знаходити, додавати та відтворювати нові відео. Усі плавно переглядають наступне відео разом.<br><br>Завдяки KoalaSync на YouTube, автоматичне відтворення сайту за замовчуванням бере на себе перевагу, перенаправляючи кожного користувача до іншого рекомендованого відео. Наша автоматична функція наступної серії («Лобі серії»), яка чудово працює на Netflix або Disney+, не працює на YouTube через ці динамічні рекомендації. Для чистих вечорів YouTube Watch2Gether кращий вибір.",
"ALT_W2G_WHEN_KOALA_TITLE": "Коли KoalaSync підходить краще",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync блищить на <strong>реальних потокових службах</strong> (Netflix, Prime Video, Disney+) і медіа-серверах, які розміщено на власному хості (Jellyfin, Plex, Emby). На відміну від Watch2Gether, який часто взагалі не може відтворювати преміальний вміст, KoalaSync синхронізує рідний програвач безпосередньо на веб-сайті.<br><br>Він працює майже на будь-якому сайті зі стандартним відеопрогравачем HTML5. Вам не потрібно створювати віртуальну кімнату на сторонньому сайті: просто активуйте розширення, приєднайтеся до лобі та почніть дивитися.",
"ALT_W2G_MAIN_DIFF_TITLE": "Головна відмінність",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether — це <strong>окремий веб-сайт</strong> із вбудованим чатом, списками відтворення та підтримкою веб-камери. KoalaSync — це <strong>мінімалістичне розширення для веб-переглядача</strong>, яке підключається безпосередньо до звичайних вкладок веб-переглядача.<br><br>Шукаєте комплексний пакет для YouTube із вбудованим чатом? Використовуйте Watch2Gether. Хочете дивитися фільми на Netflix або на власному сервері, не відволікаючись, у рідній якості (без стиснення на сервері)? KoalaSync — це чистіше рішення.",
"ALT_W2G_LIMITS_TITLE": "Чесні обмеження",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>не має вбудованих списків відтворення чи пошуку відео</strong>. На YouTube це означає, що автоматичне відтворення наступного відео не буде синхронізовано.<br><br>Крім того, <strong>немає вбудованого чату</strong>, а KoalaSync наразі працює лише у веб-переглядачах для комп’ютерів. Він розроблений на основі припущення, що ви вже розмовляєте через Discord, Teamspeak або інші голосові інструменти.",
"ALT_W2G_SUMMARY_TITLE": "Якщо коротко",
"ALT_W2G_SUMMARY_BODY": "Для спонтанних сеансів YouTube зі списками відтворення та вбудованим чатом Watch2Gether є найкращим вибором. Для потокових платформ преміум-класу (як-от Netflix, Prime Video, Disney+), власних серверів (Jellyfin, Plex, Emby) і максимальної гнучкості браузера KoalaSync є більш придатним і легким інструментом.",
"ALT_SCENER_TITLE": "KoalaSync проти Scener: яка платформа для перегляду вечірок краще підходить?",
"ALT_SCENER_META_DESC": "Чесне порівняння KoalaSync і Scener. Дізнайтеся, коли чат веб-камери Scener виграє та чому KoalaSync найкращий для перегляду фільмів без відволікання.",
"ALT_SCENER_INTRO": "KoalaSync і Scener розглядають вечірки з двох абсолютно різних точок зору. Scener — це віртуальний кінотеатр із вбудованим відеочатом та інтерактивними кімнатами. З іншого боку, KoalaSync — це мінімалістичне, дружнє до конфіденційності розширення для браузера, яке просто синхронізує елементи керування відтворенням. Який інструмент вам найбільше підходить, залежить головним чином від того, наскільки важливі для вас вбудована веб-камера та функції чату.",
"ALT_SCENER_WHEN_SCENER_TITLE": "Коли Scener є кращим вибором",
"ALT_SCENER_WHEN_SCENER_BODY": "Scener є надійним вибором, якщо вам потрібна <strong>універсальна соціальна платформа</strong> з вбудованим відео- та аудіочатом безпосередньо у вашому браузері. Scener створює віртуальну кімнату, де гравець і веб-камери ваших друзів відображаються пліч-о-пліч. Це ідеальний варіант для великих публічних вечірок або віртуальних потокових подій, де соціальний аспект знаходиться на першому місці. Однак майте на увазі, що безкоштовна базова версія підтримується рекламою, а Scener блокує багато функцій (наприклад, перегляд без реклами та необмежений відеочат) за щомісячною підпискою (5,79 доларів США на місяць або 39,99 доларів США на рік).",
"ALT_SCENER_WHEN_KOALA_TITLE": "Коли KoalaSync підходить краще",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync блищить, коли йдеться про <strong>якість відео, конфіденційність і простоту</strong>:<br><br>• <strong>Без облікових записів</strong>: Вам не потрібно реєструватися, входити в систему чи керувати профілями. Просто активуйте розширення, поділіться кодом кімнати та починайте перегляд.<br>• <strong>Справжня рідна якість (4K/HDR)</strong>: Scener транслює стиснене відео з віртуального хмарного сервера, що може призвести до втрати якості та затримки. KoalaSync синхронізує рідний програвач безпосередньо на вашому комп’ютері, тобто ви дивитеся фільми в повній роздільній здатності вашої підписки на потокове передавання.<br>• <strong>Низьке використання смуги пропускання</strong>: оскільки передаються лише контрольні дані (відтворення, пауза, мітки часу), KoalaSync практично не використовує додаткової смуги пропускання. Scener передає все відео та канали камери через хмарні сервери, що може сильно навантажувати повільніші підключення до Інтернету та старі ноутбки.<br>• <strong>100% безкоштовно та без реклами</strong>: без щомісячної плати за підписку, без реклами та трекерів.<br>• <strong>Локальні відеофайли</strong>: оскільки KoalaSync працює локально, ви навіть можете переглядати власні відеофайли (наприклад, MP4) синхронізовано з друзі. Просто перетягніть файл на вкладку браузера – Scener не може цього зробити, оскільки його програвач працює в хмарі.",
"ALT_SCENER_MAIN_DIFF_TITLE": "Головна відмінність",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener — це <strong>комерційна соціальна мережа</strong> для вечірок, яка працює на основі віртуальних хмарних браузерів і фінансується за рахунок реклами та щомісячних підписок. KoalaSync — це <strong>конфіденційність, безкоштовна утиліта синхронізації</strong>, яка підключається безпосередньо до вкладок вашого веб-переглядача. Він залишає голосовий/відеочат для таких програм, як Discord або Teamspeak, повністю зосереджуючись на тому, щоб ваше відтворення було плавним, конфіденційним і в оригінальній якості.",
"ALT_SCENER_LIMITS_TITLE": "Чесні обмеження",
"ALT_SCENER_LIMITS_BODY": "KoalaSync <strong>не підтримує вбудований чат або веб-камеру</strong>. Це суто інструмент синхронізації, для якого потрібен окремий інструмент голосового виклику на ваш вибір. Крім того, наразі KoalaSync доступний лише для робочого столу, і сумісність локальних відеофайлів повністю залежить від того, чи підтримує ваш браузер відтворення відеоформату та аудіокодеків.",
"ALT_SCENER_SUMMARY_TITLE": "Якщо коротко",
"ALT_SCENER_SUMMARY_BODY": "Для великих вечірок із вбудованим чатом через веб-камеру та соціальними функціями Scener є правильним вибором, за умови, що ви не проти реклами та преміум-плати. Якщо вам потрібен абсолютно безкоштовний, без реклами та без відволікань досвід у рідному програвачі (включно з Netflix, Prime Video, Disney+ або файлами локального браузера), і ви вже розмовляєте по телефону, KoalaSync — це чистіше та ефективніше рішення.",
"ALT_KOSMI_TITLE": "KoalaSync проти Kosmi: Яка альтернатива вечірки Netflix краще підходить?",
"ALT_KOSMI_META_DESC": "Чесне порівняння KoalaSync і Kosmi. Дізнайтеся, чому налаштування Kosmi без розширення є зручними та коли виграє рідна якість відео KoalaSync.",
"ALT_KOSMI_INTRO": "І KoalaSync, і Kosmi пропонують чудові способи перегляду Netflix, YouTube та інших платформ разом із друзями. Однак їхні базові технології принципово відрізняються. Kosmi використовує віртуальні хмарні браузери, які запускаються безпосередньо у вашому веб-браузері без встановлення розширень. KoalaSync — це легке розширення, яке синхронізує ваш локальний відеоплеєр. Який підхід вам найкраще підходить, залежить від ваших пріоритетів щодо якості відео, зручності та конфіденційності.",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "Коли Kosmi – кращий вибір",
"ALT_KOSMI_WHEN_KOSMI_BODY": "Kosmi є неперевершеним, якщо ви хочете <strong>уникнути будь-чого встановлення</strong> або хочете дивитися на таких пристроях, як планшети та смартфони. Оскільки Kosmi використовує віртуальні браузери в хмарі, все, що потрібно для приєднання, — це просте веб-посилання. Крім того, Kosmi — це універсальна платформа для спілкування: окрім синхронізованої потокової передачі, ви можете грати в багатокористувацькі ігри (наприклад, ретро-класику NES/SNES або покер) і використовувати вбудовану веб-камеру, голосовий і текстовий чат. Якщо ви хочете провести ніч у соціальних іграх і подивитися вечірку без налаштування, Kosmi — це фантастичне рішення.",
"ALT_KOSMI_WHEN_KOALA_TITLE": "Коли KoalaSync підходить краще",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync сяє, коли йдеться про <strong>власну якість відтворення, безпеку та продуктивність</strong>:<br><br>• <strong>Жодних ризиків безпеці</strong>: з Kosmi вам потрібно ввійти у свій обліковий запис Netflix або Prime на віддаленому віртуальному комп’ютері в хмарі. За допомогою KoalaSync ви безпечно входите на офіційний веб-сайт потокового передавання у своєму власному браузері, як і зазвичай. Ваші паролі ніколи не залишать вашу машину.<br>• <strong>Повна якість відео (4K/HDR)</strong>: Kosmi транслює екран віртуального браузера як стиснене відео, що може призвести до пікселізації та буферизації. KoalaSync синхронізує рідні програвачі локально: ви насолоджуєтеся фільмами в повній, кришталево чіткій роздільній здатності вашої підписки.<br>• <strong>Без затримок і зручність пропускної здатності</strong>: оскільки KoalaSync надсилає лише команди керування (відтворення/пауза/мітки часу), він використовує майже нульову пропускну здатність. Kosmi постійно транслює відео у форматі HD, що може перевантажувати повільніші з’єднання.<br>• <strong>Локальні відеофайли</strong>: якщо ви хочете переглянути приватне відео, просто перетягніть файл MP4 на вкладку браузера та синхронізуйте його. Kosmi не може отримати доступ до файлів на вашому локальному жорсткому диску.",
"ALT_KOSMI_MAIN_DIFF_TITLE": "Головна відмінність",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi — це <strong>віртуальний хмарний чат</strong>, який транслює екран віддаленого браузера, тому нікому не потрібно встановлювати розширення. KoalaSync — це <strong>локальний рівень синхронізації браузера</strong>, який підключається безпосередньо до рідного програвача на офіційному веб-сайті потокового передавання. У той час як Kosmi є більш універсальним для міні-ігор і сумісності пристроїв, KoalaSync пропонує більш безпечну, плавну та чітку трансляцію в оригінальному програвачі.",
"ALT_KOSMI_LIMITS_TITLE": "Чесні обмеження",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>потрібно встановити розширення для веб-переглядача</strong> і наразі працює лише на настільних ПК. У ньому <strong>немає вбудованого чату чи веб-камер</strong>, оскільки він розроблений з урахуванням припущення, що ви вже розмовляєте через Discord або інші голосові інструменти. Він також не пропонує вбудованих ігор.",
"ALT_KOSMI_SUMMARY_TITLE": "Якщо коротко",
"ALT_KOSMI_SUMMARY_BODY": "Kosmi ідеально підходить для вечорів звичайних ігор із ретро-класикою та легким доступом на мобільних пристроях без будь-якої інсталяції. Для кіновечорів преміум-класу на Netflix, Prime Video, Disney+ або Plex у повній якості 4K, з максимальною безпекою та мінімальним впливом на пропускну здатність, KoalaSync є очевидним переможцем.",
"ALT_TWOSEVEN_TITLE": "KoalaSync проти TwoSeven: яке рішення для вечірки під час перегляду годинників краще підходить?",
"ALT_TWOSEVEN_META_DESC": "Чесне порівняння KoalaSync і TwoSeven. Дізнайтеся, коли вбудована веб-камера TwoSeven виграє та чому KoalaSync найкраще підходить для Disney+ і Netflix.",
"ALT_TWOSEVEN_INTRO": "І KoalaSync, і TwoSeven використовують однаковий базовий підхід для вечірок перегляду: вони синхронізують оригінальний відеопрогравач безпосередньо у вашому браузері, а не транслюють стиснене відео з хмари. Це забезпечує найвищу якість відео для обох інструментів. Однак, хоча TwoSeven є комерційним порталом із вбудованим чатом через веб-камеру та рівнями підписки, KoalaSync залишається мінімалістичним, повністю безкоштовним розширенням, яке підтримує конфіденційність. Дізнайтеся, яка послуга вам найкраще підходить тут.",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "Коли TwoSeven є кращим вибором",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "TwoSeven — це правильний вибір, якщо вам потрібне <strong>універсальне рішення з вбудованою веб-камерою та аудіочатом</strong> безпосередньо у вашому браузері. Якщо ви хочете бачити своїх друзів під час перегляду, не запускаючи Discord або Teamspeak у фоновому режимі, TwoSeven пропонує таку вбудовану інтеграцію. Крім того, він працює для YouTube і кількох відкритих веб-відеоплеєрів без розширень. Він добре підходить для невеликих груп із 2–3 осіб, які бажають візуально спілкуватися під час перегляду.",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "Коли KoalaSync підходить краще",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync блищить своєю <strong>повною відсутністю плати, конфіденційністю та простотою</strong>:<br><br>• <strong>Жодної оплати</strong>: щоб синхронізувати преміум-сервіси, такі як Disney+ або Hulu, на TwoSeven, принаймні один учасник кімнати має підтримати їх на Patreon (від 3 доларів США на місяць). KoalaSync синхронізує Netflix, Prime Video, Disney+ і медіа-сервери (Jellyfin, Plex, Emby) на 100% безкоштовно та без обмежень.<br>• <strong>Абсолютна конфіденційність (без трекерів/реклами)</strong>: TwoSeven підтримує рекламу та використовує кілька трекерів від Google, Facebook та інших. KoalaSync не має реклами, трекерів і зв’язується виключно з ретрансляційним сервером, який використовує лише оперативну пам’ять.<br>• <strong>Реєстрація не потрібна</strong>: TwoSeven вимагає, щоб усі учасники створили обліковий запис і ввійшли. KoalaSync абсолютно не потребує облікових записів. Просто встановіть, введіть код кімнати та почніть перегляд.<br>• <strong>Легкий і зручний для ресурсів</strong>: інтегрована веб-камера та аудіоканали TwoSeven значно навантажують ваш ЦП і мережу. Залишаючи зв’язок таким інструментам, як Discord, KoalaSync працює надзвичайно плавно та зберігає час роботи акумулятора.",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "Головна відмінність",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven — це <strong>комерційна платформа</strong> з вимогами до реєстрації, оголошеннями, одноранговими чатами через веб-камеру та оплатою Patreon для певних потокових сервісів. KoalaSync — це <strong>безкоштовна утиліта з відкритим вихідним кодом</strong>, яка підключається безпосередньо до вкладок вашого веб-переглядача без облікових записів, трекерів або додаткових витрат, дозволяючи дивитися без відволікань у рідному програвачі.",
"ALT_TWOSEVEN_LIMITS_TITLE": "Чесні обмеження",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync не пропонує <strong>немає вбудованої веб-камери чи аудіочату</strong> та передбачає, що ви вже розмовляєте через Discord або подібний інструмент. Крім того, KoalaSync не має вбудованого накладення вікна чату, і наразі він доступний лише для робочого столу.",
"ALT_TWOSEVEN_SUMMARY_TITLE": "Якщо коротко",
"ALT_TWOSEVEN_SUMMARY_BODY": "Для невеликих груп із двох-трьох людей, які хочуть бачити один одного через веб-камери безпосередньо у веб-переглядачі та не проти підтримати підтримку Patreon для Disney+, TwoSeven — хороший варіант. Для перегляду без реклами, повністю безкоштовного перегляду приватних кіновечорів у рідній якості 4K (незалежно від того, Netflix, Prime Video, Disney+ або Jellyfin) без реєстрації, KoalaSync — чистіший і безпечніший вибір.",
"ALT_TRY_KOALASYNC": "Спробуйте KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "Керування ведучим",
"MOCK_HOST_CONTROL_TOGGLE": "Тільки я можу керувати відтворенням",
+52 -13
View File
@@ -222,19 +222,58 @@
"ALT_SCREEN_LIMITS_BODY": "KoalaSync 无法替代语音通话。如果您想在观看的同时进行交流,仍可使用 Discord、Teamspeak、Signal、WhatsApp 或您常用的任何通讯工具。<br><br>此外,每位参与者都需要在各自的设备上访问相应的视频或网页。KoalaSync 无法绕过订阅、登录验证、DRM(数字版权管理)、地域限制或平台规则。<br><br>该工具目前仅支持桌面端浏览器,不包含内置聊天或语音功能;其兼容性取决于具体的浏览器和视频播放器。",
"ALT_SCREEN_SUMMARY_TITLE": "摘要",
"ALT_SCREEN_SUMMARY_BODY": "如果您追求快速便捷,且不太在意画质、隐私或个性化控制,那么屏幕共享是最简单的选择。而当您希望每位参与者都在各自的浏览器中观看,并营造出一种真正“共同观看”的氛围时,KoalaSync 则是更理想的方案。",
"ALT_W2G_TITLE": "KoalaSync vs Watch2Gether: Which watch party solution fits better?",
"ALT_W2G_META_DESC": "An honest comparison between KoalaSync and Watch2Gether. Discover when KoalaSync's flexibility is unbeatable and why Watch2Gether is still the top choice for YouTube.",
"ALT_W2G_INTRO": "KoalaSync and Watch2Gether both solve the same problem: watching videos in sync with friends online without manually coordinating. While Watch2Gether is one of the oldest and most popular hubs for shared movie nights, KoalaSync takes a completely different, lightweight approach. Which tool is right for you depends heavily on what and where you want to watch.",
"ALT_W2G_WHEN_W2G_TITLE": "When Watch2Gether is the better choice",
"ALT_W2G_WHEN_W2G_BODY": "Watch2Gether is unbeatable for <strong>YouTube watch parties</strong>. With its built-in playlist and search, anyone in the room can easily find, add, and play new videos. Everyone watches the next video together seamlessly.<br><br>With KoalaSync on YouTube, the site's default autoplay takes over, redirecting each user to a different recommended video. Our automatic next-episode feature (\"Episode Lobby\"), which works great on Netflix or Disney+, doesn't work on YouTube due to these dynamic recommendations. For pure YouTube nights, Watch2Gether is the better choice.",
"ALT_W2G_WHEN_KOALA_TITLE": "When KoalaSync fits better",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync shines on <strong>real streaming services</strong> (Netflix, Prime Video, Disney+) and self-hosted media servers (Jellyfin, Plex, Emby). Unlike Watch2Gether, which often cannot play premium content at all, KoalaSync syncs the native player directly on the website.<br><br>It works on almost any site with a standard HTML5 video player. You don't need to set up a virtual room on a third-party site: just activate the extension, join a lobby, and start watching.",
"ALT_W2G_MAIN_DIFF_TITLE": "The main difference",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether is a <strong>standalone website</strong> with built-in chat, playlists, and webcam support. KoalaSync is a <strong>minimalist browser extension</strong> that hooks directly into your normal browser tabs.<br><br>Looking for an all-in-one package for YouTube with built-in chat? Use Watch2Gether. Want to watch movies on Netflix or your own server without distractions, in native quality (no server compression)? KoalaSync is the cleaner solution.",
"ALT_W2G_LIMITS_TITLE": "Honest limitations",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>does not have built-in playlists or video search</strong>. On YouTube, this means that autoplaying the next video won't stay in sync.<br><br>Additionally, there is <strong>no built-in chat</strong>, and KoalaSync currently only works on desktop browsers. It is designed under the assumption that you are already talking via Discord, Teamspeak, or other voice tools anyway.",
"ALT_W2G_SUMMARY_TITLE": "In short",
"ALT_W2G_SUMMARY_BODY": "For spontaneous YouTube sessions with playlists and built-in chat, Watch2Gether is the best choice. For premium streaming platforms (like Netflix, Prime Video, Disney+), self-hosted servers (Jellyfin, Plex, Emby), and maximum browser flexibility, KoalaSync is the more suitable and lightweight tool.",
"ALT_W2G_TITLE": "KoalaSync Watch2Gether:哪种手表派对解决方案更适合?",
"ALT_W2G_META_DESC": "KoalaSync Watch2Gether 之间的诚实比较。了解 KoalaSync 的灵活性何时无与伦比,以及为什么 Watch2Gether 仍然是 YouTube 的首选。",
"ALT_W2G_INTRO": "KoalaSync Watch2Gether 都解决了同样的问题:与朋友在线同步观看视频,无需手动协调。虽然 Watch2Gether 是最古老、最受欢迎的共享电影之夜中心之一,但 KoalaSync 采用了完全不同的轻量级方法。哪种工具适合您在很大程度上取决于您想要观看的内容和位置。",
"ALT_W2G_WHEN_W2G_TITLE": " Watch2Gether 是更好的选择时",
"ALT_W2G_WHEN_W2G_BODY": "对于 <strong>YouTube 观看派对</strong>来说,Watch2Gether 是无与伦比的。借助其内置的播放列表和搜索,房间中的任何人都可以轻松查找、添加和播放新视频。每个人都可以无缝地一起观看下一个视频。<br><br>借助 YouTube 上的 KoalaSync,网站的默认自动播放功能将接管,将每个用户重定向到不同的推荐视频。我们的自动下一集功能(“剧集大厅”)在 Netflix Disney+ 上运行良好,但由于这些动态推荐而无法在 YouTube 上运行。对于纯粹的 YouTube 之夜,Watch2Gether 是更好的选择。",
"ALT_W2G_WHEN_KOALA_TITLE": " KoalaSync 更适合时",
"ALT_W2G_WHEN_KOALA_BODY": "KoalaSync 在<strong>真正的流媒体服务</strong>NetflixPrime VideoDisney+)和自托管媒体服务器(JellyfinPlexEmby)上大放异彩。与通常根本无法播放优质内容的 Watch2Gether 不同,KoalaSync 直接在网站上同步本机播放器。<br><br>它几乎适用于任何具有标准 HTML5 视频播放器的网站。您无需在第三方网站上设置虚拟房间:只需激活扩展程序,加入大厅,然后开始观看。",
"ALT_W2G_MAIN_DIFF_TITLE": "主要区别",
"ALT_W2G_MAIN_DIFF_BODY": "Watch2Gether 是一个<strong>独立网站</strong>,具有内置聊天、播放列表和网络摄像头支持。 KoalaSync 是一款<strong>极简主义浏览器扩展</strong>,可直接连接到您的普通浏览器选项卡。<br><br>正在寻找具有内置聊天功能的 YouTube 一体化软件包?使用 Watch2Gether。想要在 Netflix 或您自己的服务器上不受干扰地以本机质量(无服务器压缩)观看电影吗? KoalaSync 是更干净的解决方案。",
"ALT_W2G_LIMITS_TITLE": "诚实的限制",
"ALT_W2G_LIMITS_BODY": "KoalaSync <strong>没有内置播放列表或视频搜索</strong>。在 YouTube 上,这意味着自动播放下一个视频将无法保持同步。<br><br>此外,<strong>没有内置聊天</strong>,并且 KoalaSync 目前仅适用于桌面浏览器。它的设计假设您已经通过 DiscordTeamspeak 或其他语音工具进行交谈。",
"ALT_W2G_SUMMARY_TITLE": "简而言之",
"ALT_W2G_SUMMARY_BODY": "对于带有播放列表和内置聊天功能的自发 YouTube 会话,Watch2Gether 是最佳选择。对于优质流媒体平台(如 NetflixPrime VideoDisney+)、自托管服务器(JellyfinPlexEmby)和最大的浏览器灵活性,KoalaSync 是更合适、更轻量级的工具。",
"ALT_SCENER_TITLE": "KoalaSync vs Scener:哪个观看派对平台更适合?",
"ALT_SCENER_META_DESC": "KoalaSync 和 Scener 的诚实比较。了解 Scener 的网络摄像头聊天何时获胜以及为什么 KoalaSync 最适合无干扰的电影之夜。",
"ALT_SCENER_INTRO": "KoalaSync 和 Scener 从两个完全不同的角度来看待观看派对。 Scener 是一个虚拟电影院,内置视频聊天和互动室。另一方面,KoalaSync 是一款极简、隐私友好的浏览器扩展,可以简单地同步播放控件。哪种工具最适合您主要取决于内置网络摄像头和聊天功能对您的重要性。",
"ALT_SCENER_WHEN_SCENER_TITLE": "当 Scener 是更好的选择时",
"ALT_SCENER_WHEN_SCENER_BODY": "如果您想要一个直接在浏览器中内置视频和音频聊天的<strong>一体化社交平台</strong>,那么 Scener 是一个不错的选择。 Scener 创建一个虚拟房间,玩家和朋友的网络摄像头并排显示在其中。这对于以社交为中心的大型公众观看派对或虚拟流媒体活动来说是理想的选择。但是,请记住,免费的基本版本是受广告支持的,并且 Scener 将许多功能(例如无广告观看和无限制视频聊天)锁定在每月订阅(5.79 美元/月或 39.99 美元/年)后面。",
"ALT_SCENER_WHEN_KOALA_TITLE": "当 KoalaSync 更适合时",
"ALT_SCENER_WHEN_KOALA_BODY": "KoalaSync 在<strong>视频质量、隐私和简单性</strong>方面表现出色:<br><br>• <strong>无帐户</strong>:您无需注册、登录或管理个人资料。只需激活扩展程序,共享房间代码,然后开始观看。<br>• <strong>真正的原生质量 (4K/HDR)</strong>Scener 从虚拟云服务器流式传输压缩视频,这可能会导致质量损失和滞后。 KoalaSync 直接在您的计算机上同步本机播放器,这意味着您可以以流媒体订阅的全分辨率观看电影。<br>• <strong>带宽使用率低</strong>:因为仅传输控制数据(播放、暂停、时间戳),所以 KoalaSync 几乎不使用额外的带宽。 Scener 通过云服务器流式传输整个视频和摄像头源,这会对较慢的互联网连接和旧笔记本电脑造成严重压力。<br>• <strong>100% 免费且无广告</strong>:无月租费、无广告、无跟踪器。<br>• <strong>本地视频文件</strong>:由于 KoalaSync 在本地运行,您甚至可以与朋友同步观看自己的视频文件(如 MP4)。只需将文件拖放到浏览器选项卡中即可 - Scener 无法执行此操作,因它的播放器在云中运行。",
"ALT_SCENER_MAIN_DIFF_TITLE": "主要区别",
"ALT_SCENER_MAIN_DIFF_BODY": "Scener 是一个面向观看派对的<strong>商业社交网络</strong>,由虚拟云浏览器提供支持,并通过广告和每月订阅提供资金。 KoalaSync 是一个<strong>隐私第一的免费同步实用程序</strong>,可直接连接到您的浏览器选项卡。它将语音/视频聊天留给 Discord 或 Teamspeak 等应用程序,完全专注于保持播放的流畅性、私密性和原始质量。",
"ALT_SCENER_LIMITS_TITLE": "诚实的限制",
"ALT_SCENER_LIMITS_BODY": "KoalaSync <strong>不提供内置聊天或网络摄像头支持</strong>。它纯粹是一个同步工具,需要您选择单独的语音通话工具。此外,KoalaSync 目前仅适用于桌面,本地视频文件兼容性完全取决于您的浏览器是否原生支持播放视频格式和音频编解码器。",
"ALT_SCENER_SUMMARY_TITLE": "简而言之",
"ALT_SCENER_SUMMARY_BODY": "对于具有内置网络摄像头聊天和社交功能的大型观看聚会,Scener 是正确的选择,前提是您不介意广告和付费专区。如果您想在本机播放器(包括 Netflix、Prime Video、Disney+ 或本地浏览器文件)中获得完全免费、无广告和无干扰的体验,并且您已经在进行语音通话,那么 KoalaSync 是更干净、更高效的解决方案。",
"ALT_KOSMI_TITLE": "KoalaSync 与 Kosmi:哪种 Netflix 派对替代品更适合?",
"ALT_KOSMI_META_DESC": "KoalaSync 和 Kosmi 的诚实比较。了解为什么 Kosmi 的无扩展设置很方便,以及 KoalaSync 的原生视频质量何时胜出。",
"ALT_KOSMI_INTRO": "KoalaSync 和 Kosmi 都提供了与朋友同步观看 Netflix、YouTube 和其他平台的绝佳方式。然而,它们的底层技术根本不同。 Kosmi 使用虚拟云浏览器,直接在您的网络浏览器中运行,无需安装扩展。 KoalaSync 是一个轻量级扩展,可同步您的本地视频播放器。哪种方法最适合您取决于您​​对视频质量、便利性和隐私的优先考虑。",
"ALT_KOSMI_WHEN_KOSMI_TITLE": "当 Kosmi 是更好的选择时",
"ALT_KOSMI_WHEN_KOSMI_BODY": "如果您想<strong>避免安装任何东西</strong>或想在平板电脑和智能手机等设备上观看,Kosmi 是无与伦比的。由于 Kosmi 在云端运行虚拟浏览器,因此只需一个简单的 Web 链接即可加入。此外,Kosmi 是一个一体化的聚会平台:除了同步流媒体之外,您还可以玩多人游戏(如复古 NES/SNES 经典游戏或扑克)并使用内置网络摄像头、语音和文本聊天。如果您想要一个无需设置的社交游戏之夜和观看派对,Kosmi 是一个绝佳的解决方案。",
"ALT_KOSMI_WHEN_KOALA_TITLE": "当 KoalaSync 更适合时",
"ALT_KOSMI_WHEN_KOALA_BODY": "KoalaSync 在<strong>本机播放质量、安全性和性能</strong>方面表现出色:<br><br>• <strong>无安全风险</strong>:使用 Kosmi,您必须在云中的远程虚拟计算机上登录您的 Netflix 或 Prime 帐户。使用 KoalaSync,您可以像平常一样在自己的浏览器中安全地登录官方流媒体网站。您的密码永远不会离开您的计算机。<br>• <strong>完整视频质量 (4K/HDR)</strong>Kosmi 将虚拟浏览器屏幕作为压缩视频源进行流式传输,这可能会导致像素化和缓冲。 KoalaSync 在本地同步本机播放器:您可以以订阅的完整、清晰的分辨率欣赏电影。<br>• <strong>无延迟且带宽友好</strong>:由于 KoalaSync 仅发送控制命令(播放/暂停/时间戳),因此它使用的带宽几乎为零。 Kosmi 不断传输高清视频源,这可能会压垮较慢的连接。<br>• <strong>本地视频文件</strong>:如果您想观看私人视频,只需将 MP4 文件拖放到浏览器选项卡中并同步即可。 Kosmi 无法访问本地硬盘上的文件。",
"ALT_KOSMI_MAIN_DIFF_TITLE": "主要区别",
"ALT_KOSMI_MAIN_DIFF_BODY": "Kosmi 是一个<strong>虚拟云场所</strong>,它可以传输远程浏览器的屏幕,因此无需安装扩展程序。 KoalaSync 是一个<strong>本地浏览器同步层</strong>,可直接连接到官方流媒体网站上的本机播放器。虽然 Kosmi 在迷你游戏和设备兼容性方面更加通用,但 KoalaSync 在原始播放器中提供了更安全、流畅和清晰的流媒体体验。",
"ALT_KOSMI_LIMITS_TITLE": "诚实的限制",
"ALT_KOSMI_LIMITS_BODY": "KoalaSync <strong>需要安装浏览器扩展</strong>,目前仅在台式电脑上运行。它<strong>没有内置聊天或网络摄像头</strong>,因为它的设计假设您已经通过 Discord 或其他语音工具进行交谈。它也不提供内置游戏。",
"ALT_KOSMI_SUMMARY_TITLE": "简而言之",
"ALT_KOSMI_SUMMARY_BODY": "如果想要享受复古经典的休闲游戏之夜,并且无需任何安装即可在移动设备上轻松访问,Kosmi 是理想的选择。对于 Netflix、Prime Video、Disney+ 或 Plex 上的全 4K 质量的优质电影之夜,以最高的安全性和最小的带宽影响,KoalaSync 是明显的赢家。",
"ALT_TWOSEVEN_TITLE": "KoalaSync 与 TwoSeven:哪种手表派对解决方案更适合?",
"ALT_TWOSEVEN_META_DESC": "KoalaSync 和 TwoSeven 的诚实比较。了解 TwoSeven 的内置网络摄像头何时获胜以及为什么 KoalaSync 最适合 Disney+ 和 Netflix。",
"ALT_TWOSEVEN_INTRO": "KoalaSync 和 TwoSeven 对于观看派对都使用相同的基本方法:它们直接在浏览器中同步原始视频播放器,而不是从云端传输压缩视频源。这确保了这两种工具的顶级视频质量。然而,虽然 TwoSeven 是一个具有内置网络摄像头聊天和订阅层的商业门户,但 KoalaSync 仍然是一个极简、完全免费且隐私友好的扩展。在这里找出最适合您的服务。",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_TITLE": "当 TwoSeven 是更好的选择时",
"ALT_TWOSEVEN_WHEN_TWOSEVEN_BODY": "如果您想要直接在浏览器中<strong>集成网络摄像头和音频聊天的一体化解决方案</strong>TwoSeven 是正确的选择。如果您想在观看时看到您的朋友,而无需在后台运行 Discord 或 TeamspeakTwoSeven 本身就提供了这种集成。此外,它还适用于 YouTube 和一些没有扩展的开放网络视频播放器。它非常适合想要在观看时共享视觉联系的 2 至 3 人小团体。",
"ALT_TWOSEVEN_WHEN_KOALA_TITLE": "当 KoalaSync 更适合时",
"ALT_TWOSEVEN_WHEN_KOALA_BODY": "KoalaSync 以其<strong>完全不收费、隐私和简单</strong>而大放异彩:<br><br>• <strong>无付费墙</strong>:要在 TwoSeven 上同步观看 Disney+ 或 Hulu 等高级服务,至少一名房间成员必须在 Patreon 上支持它们(起价为 3 美元/月)。 KoalaSync 同步 Netflix、Prime Video、Disney+ 和自托管媒体服务器(Jellyfin、Plex、Emby),100% 免费,零限制。<br>• <strong>绝对隐私(无跟踪器/广告)</strong>TwoSeven 支持广告,并使用来自 Google、Facebook 和其他公司的多个跟踪器。 KoalaSync 没有广告,没有跟踪器,并且仅与仅 RAM 的中继服务器进行通信。<br>• <strong>无需注册</strong>TwoSeven 要求所有参与者创建帐户并登录。KoalaSync 完全无需帐户。只需安装,输入房间代码,然后开始观看。<br>• <strong>轻量且资源友好</strong>TwoSeven 的集成网络摄像头和音频源会给您的 CPU 和网络带来沉重负载。通过将通信留给 Discord 等工具,KoalaSync 运行极其流畅并延长电池寿命。",
"ALT_TWOSEVEN_MAIN_DIFF_TITLE": "主要区别",
"ALT_TWOSEVEN_MAIN_DIFF_BODY": "TwoSeven 是一个<strong>商业平台</strong>,具有注册要求、广告、点对点网络摄像头聊天和针对特定流媒体服务的 Patreon 付费专区。 KoalaSync 是一款<strong>免费、开源实用程序</strong>,可直接连接到您的浏览器选项卡,无需帐户、跟踪器或额外费用,从而可以在本机播放器中无干扰地观看。",
"ALT_TWOSEVEN_LIMITS_TITLE": "诚实的限制",
"ALT_TWOSEVEN_LIMITS_BODY": "KoalaSync <strong>不提供内置网络摄像头或音频聊天</strong>,并假设您已经通过 Discord 或类似工具进行通话。此外,KoalaSync 没有内置的聊天框覆盖层,目前仅适用于桌面。",
"ALT_TWOSEVEN_SUMMARY_TITLE": "简而言之",
"ALT_TWOSEVEN_SUMMARY_BODY": "对于两三个人组成的小团体来说,他们希望直接在浏览器中通过网络摄像头看到彼此,并且不介意支持 Patreon 以获得 Disney+ 支持,TwoSeven 是一个不错的选择。对于无需注册即可获得无广告、完全免费的原生 4K 质量(无论是 Netflix、Prime Video、Disney+ 或 Jellyfin)的私人电影之夜,KoalaSync 是更干净、更安全的选择。",
"ALT_TRY_KOALASYNC": "试用 KoalaSync",
"MOCK_HOST_CONTROL_LABEL": "主持人控制",
"MOCK_HOST_CONTROL_TOGGLE": "只有我可以控制播放",
+86 -7
View File
@@ -25,24 +25,103 @@
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "Privacy Policy",
"url": "https://sync.koalastuff.net/privacy",
"description": "Privacy Policy of KoalaSync - We take data security and transparency seriously. Learn about our zero-tracking, zero-log, and zero-cookie approach.",
"inLanguage": "en",
"isPartOf": {
"@type": "WebSite",
"name": "KoalaSync",
"url": "https://sync.koalastuff.net/"
}
}
</script>
<!-- Mobile Browser Theme Styling -->
<meta name="theme-color" content="#0f172a">
<meta name="theme-color" content="#10190e">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<script src="lang-init.min.js"></script>
</head>
<body>
<div class="bg-blobs">
<div class="blob blob-1"></div>
<div class="blob blob-2"></div>
<div class="blob blob-3"></div>
<div class="bg-nature" aria-hidden="true">
<div class="bg-dusk-tint"></div>
<div class="bg-depth-day">
<div class="bg-godrays">
<span class="godray godray-1"></span>
<span class="godray godray-2"></span>
<span class="godray godray-3"></span>
</div>
<div class="bg-canopy"></div>
<span class="canopy-arc canopy-arc-1"></span>
<span class="canopy-arc canopy-arc-2"></span>
<span class="canopy-arc canopy-arc-3"></span>
<span class="canopy-arc canopy-arc-4"></span>
</div>
<div id="bamboo-far">
<span class="bamboo-stalk far-1"></span>
<span class="bamboo-stalk far-2"></span>
<span class="bamboo-stalk far-3"></span>
<span class="bamboo-stalk far-4"></span>
<span class="bamboo-stalk far-5"></span>
</div>
<div id="bamboo-near">
<div class="bamboo-stalk near-1">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
<i class="bamboo-leaf leaf-2"></i>
</div>
<div class="bamboo-stalk near-2">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
<div class="bamboo-stalk near-3">
<i class="bamboo-node node-1"></i>
<i class="bamboo-node node-2"></i>
<i class="bamboo-node node-3"></i>
<i class="bamboo-leaf leaf-1"></i>
</div>
</div>
<span class="fall-leaf fall-leaf-1"><i></i></span>
<span class="fall-leaf fall-leaf-2"><i></i></span>
<span class="fall-leaf fall-leaf-3"><i></i></span>
<span class="fall-leaf fall-leaf-4"><i></i></span>
<span class="fall-leaf fall-leaf-5"><i></i></span>
<span class="fall-leaf fall-leaf-6"><i></i></span>
<span class="fall-leaf fall-leaf-7"><i></i></span>
<span class="fall-leaf fall-leaf-8"><i></i></span>
<span class="bg-grass bg-grass-1"></span>
<span class="bg-grass bg-grass-2"></span>
<span class="bg-grass bg-grass-3"></span>
<span class="bg-grass bg-grass-4"></span>
<div class="bg-depth-dusk">
<div class="bg-mist bg-mist-1"></div>
<div class="bg-mist bg-mist-2"></div>
<div class="bg-horizon"></div>
<span class="firefly-wrap fw-1"><span class="firefly"></span></span>
<span class="firefly-wrap fw-2"><span class="firefly"></span></span>
<span class="firefly-wrap fw-3"><span class="firefly"></span></span>
<span class="firefly-wrap fw-4"><span class="firefly"></span></span>
<span class="firefly-wrap fw-5"><span class="firefly"></span></span>
<span class="firefly-wrap fw-6"><span class="firefly"></span></span>
</div>
<div class="bg-light-sweep"></div>
<div class="bg-grain"></div>
</div>
<nav>
<div class="container nav-content">
<a href="./" class="logo-area" style="text-decoration: none;">
<img src="assets/NewLogoIcon.webp" alt="KoalaSync Logo" width="40" height="40">
<img src="assets/NewLogoIcon_128.webp" alt="KoalaSync Logo" width="40" height="40">
<span>KoalaSync</span>
</a>
<div class="nav-links">
@@ -82,7 +161,7 @@
<main class="legal-content">
<div class="legal-card" data-reveal style="padding: 2rem;">
<div style="display: flex; justify-content: center;">
<img src="assets/KoalaPrivacy.webp" alt="Cute Koala representing privacy and data security" class="legal-mascot" width="180" height="180">
<img src="assets/KoalaPrivacy-180.webp" srcset="assets/KoalaPrivacy-180.webp 180w, assets/KoalaPrivacy-360.webp 360w" sizes="180px" alt="Cute Koala representing privacy and data security" class="legal-mascot" width="180" height="180">
</div>
<h1>Privacy Policy</h1>
<p style="text-align: center; text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.8rem; border-bottom: 1px solid var(--glass-border); padding-bottom: 1.5rem; margin-bottom: 2rem;">
+2 -2
View File
@@ -4,8 +4,8 @@
"description": "Real-time video synchronization for friends. Privacy-first, open source.",
"start_url": "/",
"display": "standalone",
"background_color": "#0f172a",
"theme_color": "#0f172a",
"background_color": "#10190e",
"theme_color": "#10190e",
"icons": [
{
"src": "/assets/NewLogoIcon_64.webp",
-1348
View File
File diff suppressed because it is too large Load Diff
+18 -5230
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+30
View File
@@ -0,0 +1,30 @@
/* --- Alternatives Hub Styles --- */
.guide-card {
transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.25s ease, border-color 0.25s ease !important;
}
.guide-card:hover {
transform: translateY(-4px);
background-color: rgba(255, 255, 255, 0.07) !important;
border-color: rgba(255, 255, 255, 0.22) !important;
box-shadow: 0 12px 24px -10px rgba(0, 0, 0, 0.4);
}
html.theme-light .guide-card {
background-color: var(--card-surface) !important;
border-color: var(--card-border) !important;
}
html.theme-light .guide-card:hover {
background-color: var(--card) !important;
border-color: oklch(0.52 0.12 150 / 0.35) !important;
}
.guide-card .btn-primary {
transition: background-color 0.2s ease, transform 0.1s ease;
}
.guide-card .btn-primary:active {
transform: scale(0.97);
}
@media (max-width: 640px) {
.guides-grid {
grid-template-columns: 1fr !important;
gap: 1.25rem !important;
}
}
File diff suppressed because it is too large Load Diff
+1548
View File
File diff suppressed because it is too large Load Diff
+941
View File
@@ -0,0 +1,941 @@
/* --- Hero Section --- */
.hero {
min-height: 100svh;
display: flex;
/* Centre the hero content vertically so the empty space is balanced above
and below instead of pooling under the CTAs. Padding-top only needs to
clear the fixed nav. */
align-items: center;
padding-top: clamp(6rem, 9vh, 8rem);
padding-bottom: clamp(3rem, 6vh, 5rem);
}
.hero-grid {
display: grid;
/* Single column until the interactive demo appears (1024px). Below that the
headline gets the full width and the install CTAs stay prominent while the
demo stacks underneath, matching the demo's own 1024px breakpoint. */
grid-template-columns: minmax(0, 1fr);
align-content: center;
/* Keep the whole hero vertically centered. Do not use grid alignment to fix
the demo top edge; that moves the headline and breaks the hero balance. */
align-items: center;
gap: 3rem;
text-align: left;
width: 100%;
}
@media (min-width: 1024px) {
.container {
max-width: 1200px;
}
.hero-grid {
grid-template-columns: 1.35fr 1fr;
gap: 3.5rem;
}
.cta-group {
gap: 0.75rem;
}
.cta-group .btn {
padding: 0.8rem 1.35rem;
}
}
.hero-text h1 {
font-size: clamp(2.9rem, 4.1vw, 4rem);
font-weight: 800;
line-height: 1.12;
margin-bottom: 1.4rem;
padding-bottom: 0.1em;
color: var(--text);
letter-spacing: -0.02em;
}
.hero-text h1 .hero-highlight {
background: linear-gradient(90deg, var(--accent-green), var(--accent-terracotta), var(--accent-green));
background-size: 300% 100%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
white-space: nowrap;
animation: hero-gradient-pan 10s linear infinite;
/* background-clip: text only paints inside the layout box; with the
negative h1 letter-spacing the last glyph overhangs it and gets cut
off. Invisible padding extends the paint area without moving text. */
padding-right: 0.08em;
margin-right: -0.08em;
}
@keyframes hero-gradient-pan {
from { background-position: 0% 50%; }
to { background-position: 300% 50%; }
}
@media (prefers-reduced-motion: reduce) {
.hero-text h1 .hero-highlight {
animation: none;
}
}
.hero-text p, .hero-subtitle {
font-size: 1.25rem;
color: var(--text-muted);
margin-bottom: 1.9rem;
max-width: 600px;
font-weight: 400;
line-height: 1.6;
}
.hero-mascot-container {
position: relative;
display: block;
margin-bottom: -0.5rem;
margin-left: 2.2rem;
}
.hero-lookdown-mascot {
display: block;
width: 90px;
height: auto;
}
/* Changelog link as the koala's comic speech bubble. Absolutely positioned
so it never moves the koala out of its spot above the install buttons. */
.koala-speech-bubble {
position: absolute;
left: 108px;
top: 0.2rem;
width: max-content;
max-width: min(240px, calc(100% - 120px));
display: block;
text-decoration: none;
text-align: left;
background: oklch(0.27 0.035 130 / 0.95);
border: 1px solid oklch(0.68 0.13 150 / 0.45);
border-radius: 14px;
border-bottom-left-radius: 4px;
padding: 0.6rem 0.9rem;
line-height: 1.35;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
animation: bubble-float 4s ease-in-out infinite;
transition: border-color 0.25s ease, box-shadow 0.25s ease;
}
/* Tail: outline triangle + fill triangle so it reads as part of the bubble */
.koala-speech-bubble::before,
.koala-speech-bubble::after {
content: '';
position: absolute;
width: 0;
height: 0;
}
.koala-speech-bubble::before {
left: -11px;
bottom: 10px;
border-top: 8px solid transparent;
border-bottom: 4px solid transparent;
border-right: 11px solid oklch(0.68 0.13 150 / 0.45);
}
.koala-speech-bubble::after {
left: -9px;
bottom: 11px;
border-top: 7px solid transparent;
border-bottom: 3px solid transparent;
border-right: 10px solid oklch(0.27 0.035 130 / 0.95);
}
.koala-speech-bubble:hover {
border-color: oklch(0.68 0.13 150 / 0.85);
box-shadow: 0 8px 28px oklch(0.68 0.13 150 / 0.35);
}
.koala-speech-bubble .version-text-en,
.koala-speech-bubble .version-text-de {
display: block;
}
.koala-speech-bubble .bubble-title {
display: block;
font-size: 0.85rem;
font-weight: 800;
color: var(--text);
letter-spacing: 0;
white-space: nowrap;
}
.koala-speech-bubble .bubble-sub {
display: block;
font-size: 0.72rem;
font-weight: 600;
color: var(--accent);
margin-top: 2px;
}
html.theme-light .koala-speech-bubble {
background: rgba(255, 255, 255, 0.96);
box-shadow: 0 8px 24px oklch(0.20 0.025 140 / 0.12);
}
html.theme-light .koala-speech-bubble::after {
border-right-color: rgba(255, 255, 255, 0.96);
}
@keyframes bubble-float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
.koala-speech-bubble {
animation: none;
}
}
/* Stacked hero (below the 1024px demo breakpoint): the text block owns the
full row, so the whole column headline, subtitle, koala, CTAs reads
as one centered axis instead of a left-aligned half of a two-column grid. */
@media (max-width: 1023px) {
.hero-grid {
text-align: center;
}
/* Lift the desktop measure cap: the text block is the full row here,
so a left-flushed 42rem box would sit visibly off-center. */
.hero-text {
max-width: none;
}
.hero-text p,
.hero-subtitle,
.hero-text .cta-trust {
margin-inline: auto;
}
.cta-group {
justify-content: center;
}
/* The koala keeps standing on the active install CTA; app.js updates the
offset from the real button geometry when the row wraps. */
.hero-mascot-container {
--hero-mascot-offset: 0px;
margin-left: 0;
display: flex;
justify-content: center;
}
.hero-lookdown-mascot {
transform: translateX(var(--hero-mascot-offset));
}
.koala-speech-bubble {
left: calc(50% + var(--hero-mascot-offset) + 50px);
right: 0.75rem;
top: 0.3rem;
max-width: 240px;
padding: 0.5rem 0.75rem;
}
.koala-speech-bubble .bubble-title {
font-size: 0.8rem;
}
.koala-speech-bubble .bubble-sub {
font-size: 0.68rem;
}
/* The relative release time is too much text for the small mobile bubble */
.koala-speech-bubble .bubble-ago {
display: none;
}
}
.cta-group {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
/* Quiet trust line under the install buttons; answers "is it free, is it
legit, do I need an account" right at the moment of the click decision. */
.hero-text .cta-trust {
margin-top: 0.85rem;
margin-bottom: 0;
font-size: 0.8rem;
font-weight: 500;
color: var(--text-muted);
opacity: 0.75;
letter-spacing: 0.01em;
max-width: none;
}
.btn {
padding: 0.85rem 1.75rem;
border-radius: 12px;
font-weight: 600;
text-decoration: none;
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1), color 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.95rem;
}
.btn-primary {
background: linear-gradient(135deg, oklch(0.48 0.13 150), oklch(0.39 0.10 145));
color: #fff;
border: 1px solid oklch(0.72 0.11 95 / 0.24);
box-shadow: 0 12px 24px -8px oklch(0.38 0.11 148 / 0.65), 0 0 0 1px oklch(0.80 0.08 90 / 0.06) inset;
}
.btn-primary:hover {
background: linear-gradient(135deg, oklch(0.54 0.14 150), oklch(0.44 0.11 145));
transform: translateY(-2px);
box-shadow: 0 18px 32px -8px oklch(0.38 0.11 148 / 0.75), 0 0 18px oklch(0.68 0.13 150 / 0.18);
}
.btn-firefox {
background: oklch(0.62 0.14 45);
color: white;
box-shadow: 0 10px 15px -3px oklch(0.62 0.14 45 / 0.3);
}
.btn-firefox:hover {
background: oklch(0.68 0.14 45);
transform: translateY(-2px);
box-shadow: 0 20px 25px -5px oklch(0.62 0.14 45 / 0.4);
}
.btn-secondary {
background: var(--card);
color: var(--text);
border: 1px solid var(--glass-border);
}
.btn-secondary:hover {
background: oklch(0.30 0.03 125);
transform: translateY(-2px);
}
.btn-demo-mobile {
display: none;
border: 1px solid oklch(0.68 0.13 150 / 0.34);
cursor: pointer;
font: inherit;
}
.btn-demo-mobile svg {
flex-shrink: 0;
}
/* Install buttons: compact by default (just the browser name) so all three
CTAs fit one line; the detected browser expands to the full call to action.
The GitHub button stays compact always. */
.btn-label-full { display: none; }
.btn-install:not(.is-detected),
.btn-compact {
padding: 0.62rem 1.05rem;
font-size: 0.9rem;
gap: 0.4rem;
}
.btn-install.is-detected .btn-label-short { display: none; }
.btn-install.is-detected .btn-label-full { display: inline; }
.version-badge {
display: inline-block;
background: oklch(0.68 0.13 150 / 0.1);
color: var(--accent);
padding: 0.4rem 1rem;
border-radius: 99px;
font-size: 0.8rem;
font-weight: 700;
margin-bottom: 1.5rem;
border: 1px solid oklch(0.68 0.13 150 / 0.3);
letter-spacing: 0.05em;
text-transform: uppercase;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s, background 0.2s;
}
.version-badge-below {
margin-bottom: 0;
margin-top: 1.5rem;
}
.version-badge:hover {
background: oklch(0.68 0.13 150 / 0.2);
box-shadow: 0 0 16px oklch(0.68 0.13 150 / 0.3);
transform: translateY(-1px);
}
/* --- Interactive CSS Extension Mockup --- */
.hero-mockup-wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}
.extension-mockup {
width: 100%;
max-width: 320px;
height: 528px;
background: oklch(0.20 0.025 140);
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.08);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4), 0 0 20px oklch(0.68 0.13 150 / 0.15);
display: flex;
flex-direction: column;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
overflow: hidden;
position: relative;
user-select: none;
padding: 14px;
padding-bottom: 0;
box-sizing: border-box;
}
.mock-header-row {
display: flex;
align-items: center;
margin-bottom: 12px;
flex-shrink: 0;
}
.mock-header-title {
font-size: 18px;
margin: 0;
color: var(--accent);
letter-spacing: 1px;
text-transform: uppercase;
display: inline-flex;
align-items: center;
gap: 8px;
font-weight: 800;
}
.mock-header-title picture {
display: contents;
}
.mock-header-title img {
width: 28px;
height: 28px;
object-fit: contain;
border-radius: 6px;
}
.mock-version-link {
margin-left: auto;
display: flex;
align-items: center;
gap: 4px;
font-size: 10px;
color: var(--text-muted);
text-decoration: none;
opacity: 0.5;
transition: opacity 0.2s, color 0.2s;
cursor: pointer;
}
.mock-version-link:hover {
opacity: 1;
color: var(--accent);
}
/* Close button for the hero demo popup (hidden in the static mobile mockup) */
.mock-close-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
margin-left: 8px;
padding: 0;
flex-shrink: 0;
background: transparent;
border: none;
border-radius: 6px;
color: var(--text-muted);
cursor: pointer;
transition: color 0.2s, background 0.2s;
}
.mock-close-btn:hover {
color: #fff;
background: rgba(255, 255, 255, 0.1);
}
@media (max-width: 1024px) {
.mock-close-btn {
display: none;
}
}
.mock-tabs {
display: flex;
gap: 4px;
background: oklch(0.27 0.035 130);
padding: 4px;
border-radius: 12px;
margin-bottom: 14px;
flex-shrink: 0;
}
.mock-tab {
flex: 1;
background: none;
border: none;
color: var(--text-muted);
font-size: 0.75rem;
font-weight: 600;
padding: 7px 4px;
cursor: pointer;
border-radius: 8px;
transition: color 0.2s, background-color 0.2s;
text-align: center;
}
.mock-tab:hover {
color: var(--text);
}
.mock-tab.active {
background: var(--accent);
color: var(--text-on-green);
}
.mock-body {
flex: 1;
overflow-y: auto;
padding: 0;
padding-bottom: 12px;
display: flex;
flex-direction: column;
font-size: 0.8rem;
scrollbar-width: none; /* Firefox */
}
.mock-body::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera */
}
.mock-screen {
display: none;
flex-direction: column;
gap: 10px;
}
.mock-screen.active {
display: flex;
}
/* Common Mockup Components */
.mock-card {
background: oklch(0.27 0.035 130);
border: 1px solid oklch(0.32 0.03 125);
border-radius: 8px;
padding: 10px;
}
.mock-label {
font-size: 0.65rem;
font-weight: 700;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 0.3rem;
}
.mock-section-label {
display: block;
font-size: 11px;
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: 4px;
font-weight: 700;
}
.mock-input {
background: oklch(0.27 0.035 130);
border: 1px solid oklch(0.32 0.03 125);
border-radius: 8px;
color: white;
padding: 8px 10px;
font-size: 0.75rem;
width: 100%;
outline: none;
}
.mock-btn {
background: var(--accent);
color: var(--text-on-green);
border: none;
border-radius: 6px;
padding: 0.5rem;
font-weight: 600;
font-size: 0.75rem;
cursor: pointer;
transition: background 0.2s;
text-align: center;
}
.mock-btn:hover {
background: oklch(0.60 0.12 150);
}
/* Room Tab Details */
.mock-joined-room {
display: flex;
justify-content: space-between;
align-items: center;
background: oklch(0.68 0.13 150 / 0.1);
border: 1px solid oklch(0.68 0.13 150 / 0.2);
border-radius: 8px;
padding: 0.6rem 0.75rem;
}
.mock-room-name {
font-weight: 700;
color: var(--accent);
font-size: 0.85rem;
}
.mock-server-badge {
background: oklch(0.68 0.13 150 / 0.2);
color: var(--accent);
font-size: 0.6rem;
font-weight: 700;
padding: 2px 6px;
border-radius: 4px;
}
.mock-invite-box {
display: flex;
gap: 0.35rem;
}
.mock-invite-box input {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.demo-room-empty {
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 10px;
padding: 24px 10px;
text-align: center;
}
.demo-room-empty img {
border-radius: 10px;
opacity: 0.85;
box-shadow: 0 4px 12px oklch(0.68 0.13 150 / 0.2);
}
.demo-room-empty-text {
font-size: 0.8rem;
color: var(--text-muted);
font-weight: 600;
}
.demo-create-room-btn {
background: var(--accent);
border: none;
color: var(--text-on-green);
font-weight: 700;
padding: 10px 18px;
border-radius: 10px;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.demo-create-room-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px oklch(0.68 0.13 150 / 0.4);
}
.demo-create-room-btn:active {
transform: scale(0.96);
}
.mock-peer-list {
display: flex;
flex-direction: column;
gap: 0.4rem;
}
.mock-peer-item {
display: flex;
flex-direction: column;
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(255, 255, 255, 0.03);
border-radius: 8px;
padding: 0.45rem 0.55rem;
}
.mock-peer-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.2rem;
}
.mock-peer-name {
font-weight: 700;
color: var(--text);
}
.mock-peer-meta {
font-size: 0.65rem;
color: var(--text-muted);
}
.mock-peer-tab {
font-size: 0.7rem;
color: var(--accent);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mock-peer-status {
font-size: 0.65rem;
color: var(--text-muted);
display: flex;
align-items: center;
gap: 0.25rem;
}
/* Sync Tab Details */
.mock-target-box {
display: flex;
align-items: center;
gap: 0.4rem;
background: oklch(0.62 0.14 45 / 0.1);
border: 1px solid oklch(0.62 0.14 45 / 0.2);
color: oklch(0.72 0.13 50);
padding: 0.5rem 0.6rem;
border-radius: 8px;
font-weight: 600;
font-size: 0.7rem;
}
.mock-ctrl-buttons {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
}
.mock-btn-play { background: oklch(0.68 0.13 150); }
.mock-btn-play:hover { background: oklch(0.60 0.12 150); }
.mock-btn-pause { background: oklch(0.55 0.15 25); color: #fff; }
.mock-btn-pause:hover { background: oklch(0.48 0.14 25); }
.mock-btn-force { background: var(--accent); grid-column: span 2; }
/* Contrast-safe palette for the decorative hero demo. Lighthouse/axe audits
sighted text contrast even inside aria-hidden, so every walkthrough state
must meet WCAG AA. Accent shown as text gets a lighter indigo; buttons that
put white text on a colour get a darker shade (these beat inline styles). */
.hero-demo-scene {
--accent: oklch(0.80 0.10 150);
}
/* The step-3 sync theater reuses the film SVG and must follow the same
day/night palette; --accent stays hero-only (its cards sit on the page
surface, not on the demo sky). */
.hero-demo-scene,
.illus-sync-theater {
--demo-sky-top: oklch(0.22 0.055 152);
--demo-sky-mid: oklch(0.145 0.035 150);
--demo-sky-bottom: oklch(0.075 0.018 145);
--demo-glow: oklch(0.76 0.13 150 / 0.34);
--demo-stars: oklch(0.94 0.025 95);
--demo-moon: oklch(0.97 0.025 92);
--demo-mountain: oklch(0.18 0.055 148 / 0.9);
--demo-midground: oklch(0.22 0.065 145 / 0.88);
--demo-foreground: oklch(0.065 0.025 145);
--demo-card: oklch(0.18 0.032 142);
--demo-toolbar: oklch(0.12 0.025 142);
--demo-control-fade: oklch(0.055 0.015 145 / 0.94);
--demo-track: oklch(0.92 0.02 95 / 0.2);
}
.hero-demo-scene .mock-tab.active,
.hero-demo-scene .mock-btn-force,
.hero-demo-scene #demo-force-sync,
.hero-demo-scene .demo-create-room-btn {
background: oklch(0.42 0.09 150) !important;
color: #fff;
}
.hero-demo-scene .mock-btn-play {
background: oklch(0.50 0.11 150) !important;
}
.hero-demo-scene .mock-btn-pause,
.hero-demo-scene #demo-room-joined > button.mock-btn {
background: oklch(0.45 0.14 25) !important;
}
.hero-demo-scene .mock-version-link {
opacity: 0.85;
}
html.theme-light .hero-demo-scene {
--accent: oklch(0.60 0.12 150);
}
html.theme-light .hero-demo-scene,
html.theme-light .illus-sync-theater {
--demo-sky-top: oklch(0.86 0.085 78);
--demo-sky-mid: oklch(0.76 0.095 112);
--demo-sky-bottom: oklch(0.54 0.10 150);
--demo-glow: oklch(0.92 0.13 72 / 0.44);
--demo-stars: oklch(0.98 0.025 90);
--demo-moon: oklch(0.99 0.025 88);
--demo-mountain: oklch(0.48 0.095 150 / 0.82);
--demo-midground: oklch(0.40 0.10 148 / 0.8);
--demo-foreground: oklch(0.24 0.075 145);
--demo-card: oklch(0.985 0.008 95);
--demo-toolbar: oklch(0.955 0.014 100);
--demo-control-fade: oklch(0.16 0.035 145 / 0.88);
--demo-track: oklch(0.98 0.01 95 / 0.34);
}
html.theme-light .hero-demo-scene .demo-tab-card {
background: var(--demo-card);
border-color: oklch(0.20 0.025 140 / 0.1);
box-shadow:
0 18px 38px oklch(0.20 0.025 140 / 0.16),
0 0 28px oklch(0.82 0.10 85 / 0.14),
inset 0 1px rgba(255, 255, 255, 0.9);
}
html.theme-light .hero-demo-scene .demo-tab-titlebar {
background: var(--demo-toolbar);
border-bottom-color: oklch(0.88 0.015 90);
color: oklch(0.45 0.02 110);
}
html.theme-light .hero-demo-scene .demo-tab-dots i {
background: oklch(0.78 0.02 90);
}
html.theme-light .hero-demo-scene .demo-ext-launcher {
background: #ffffff;
border-color: oklch(0.78 0.02 90);
}
html.theme-light .hero-demo-scene .demo-sync-chip {
background: oklch(0.55 0.12 150 / 0.1);
border-color: oklch(0.55 0.12 150 / 0.26);
color: oklch(0.40 0.10 150);
}
.mock-status-display {
display: flex;
align-items: center;
justify-content: space-between;
}
.mock-status-pill {
display: inline-flex;
align-items: center;
gap: 0.3rem;
background: oklch(0.68 0.13 150 / 0.1);
border: 1px solid oklch(0.68 0.13 150 / 0.2);
color: oklch(0.68 0.13 150);
padding: 2px 8px;
border-radius: 99px;
font-size: 0.65rem;
font-weight: 700;
}
.mock-log-item {
font-size: 0.7rem;
color: var(--text-muted);
border-left: 2px solid var(--accent);
padding-left: 0.4rem;
margin-top: 0.4rem;
}
/* Settings Tab Details */
.mock-settings-row {
display: flex;
align-items: flex-start;
gap: 0.5rem;
margin-bottom: 0.6rem;
}
.mock-settings-row input[type="checkbox"] {
margin-top: 0.2rem;
cursor: pointer;
}
.mock-settings-row label {
cursor: pointer;
font-weight: 600;
}
.mock-settings-row p {
font-size: 0.65rem;
color: var(--text-muted);
margin-top: 0.1rem;
}
/* Mock Toggle Switch Details */
.mock-toggle-switch {
position: relative;
display: inline-block;
width: 36px;
height: 20px;
flex-shrink: 0;
}
.mock-toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.mock-slider {
position: absolute;
cursor: default;
top: 0; left: 0; right: 0; bottom: 0;
background-color: oklch(0.32 0.03 125);
transition: .3s;
border-radius: 20px;
}
.mock-slider:before {
position: absolute;
content: "";
height: 14px;
width: 14px;
left: 3px;
bottom: 3px;
background-color: oklch(0.68 0.02 100);
transition: .3s;
border-radius: 50%;
}
input:checked + .mock-slider {
background-color: var(--accent);
}
input:checked + .mock-slider:before {
transform: translateX(16px);
background-color: white;
}
/* Dev Tab Details */
.mock-diagnostic-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.4rem;
}
.mock-diag-box {
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(255, 255, 255, 0.04);
border-radius: 6px;
padding: 0.4rem;
}
.mock-diag-box .diag-val {
font-family: monospace;
font-weight: 700;
color: var(--accent);
font-size: 0.75rem;
}
+41
View File
@@ -0,0 +1,41 @@
/* --- Join Page Loading Spinner --- */
.join-spinner {
width: 36px;
height: 36px;
border: 3px solid oklch(0.68 0.13 150 / 0.2);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin: 0 auto 0.75rem;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* --- Reduced Motion --- */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
[data-reveal] {
opacity: 1;
transform: none;
}
.illus-typing-text::after {
animation: none;
}
.illus-timeline-progress {
animation: none;
width: 60%;
}
.illus-sync-pulse {
animation: none;
}
.illus-extension-icon {
animation: none;
}
}
+136
View File
@@ -0,0 +1,136 @@
/* --- Join & Invitation Page Visuals --- */
.join-status-visual {
margin-bottom: 2rem;
position: relative;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.join-status-mascot {
display: block;
width: 140px;
height: auto;
z-index: 2;
filter: drop-shadow(0 4px 12px rgba(0,0,0,0.15));
}
.join-status-mascot.searching-mascot {
width: 175px; /* Slightly wider due to antenna to keep main body scale identical */
}
.join-status-pulse {
animation: mascot-gentle-pulse 2s ease-in-out infinite;
}
@keyframes mascot-gentle-pulse {
0% {
transform: scale(0.96);
filter: drop-shadow(0 4px 10px oklch(0.68 0.13 150 / 0.15));
}
50% {
transform: scale(1.04);
filter: drop-shadow(0 8px 20px oklch(0.68 0.13 150 / 0.35));
}
100% {
transform: scale(0.96);
filter: drop-shadow(0 4px 10px oklch(0.68 0.13 150 / 0.15));
}
}
.legal-mascot {
display: block;
width: 180px;
height: auto;
margin: -0.75rem auto 0.4rem auto;
filter: drop-shadow(0 4px 12px rgba(0,0,0,0.15));
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.legal-mascot:hover {
transform: scale(1.06) translateY(-4px) rotate(1.5deg);
}
.selfhost-mascot {
display: block;
width: 220px;
height: auto;
margin: 0 auto;
filter: drop-shadow(0 6px 14px oklch(0.15 0.02 145 / 0.22));
}
.status-ring {
position: absolute;
width: 90px;
height: 90px;
border-radius: 50%;
background: oklch(0.68 0.13 150 / 0.05);
border: 2px dashed oklch(0.68 0.13 150 / 0.25);
z-index: 1;
}
.status-ring.active-pulse {
animation: radar-pulse 3s cubic-bezier(0.25, 0.8, 0.25, 1) infinite;
}
@keyframes radar-pulse {
0% {
transform: scale(0.85);
opacity: 0.9;
border-color: oklch(0.68 0.13 150 / 0.3);
box-shadow: 0 0 0 0px oklch(0.68 0.13 150 / 0.15);
}
50% {
transform: scale(1.18);
opacity: 0.35;
border-color: oklch(0.75 0.10 150 / 0.2);
box-shadow: 0 0 0 15px oklch(0.75 0.10 150 / 0);
}
100% {
transform: scale(0.85);
opacity: 0.9;
border-color: oklch(0.68 0.13 150 / 0.3);
box-shadow: 0 0 0 0px oklch(0.68 0.13 150 / 0.15);
}
}
.join-card-actions {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: 100%;
}
.join-card-actions .btn {
width: 100%;
justify-content: center;
padding: 1.1rem;
font-size: 0.88rem;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.join-card-actions .btn svg {
margin-right: 0.3rem;
flex-shrink: 0;
}
.join-card-actions .btn img {
margin-right: 0.3rem;
flex-shrink: 0;
}
.btn-success {
background: var(--accent-green);
color: var(--text-on-green) !important;
box-shadow: 0 10px 15px -3px oklch(0.68 0.13 150 / 0.3);
}
.btn-success:hover {
background: oklch(0.60 0.12 150);
transform: translateY(-2px);
box-shadow: 0 20px 25px -5px oklch(0.68 0.13 150 / 0.4);
}
+333
View File
@@ -0,0 +1,333 @@
/* --- Language Toggle --- */
html.lang-de [lang="en"] {
display: none !important;
}
html:not(.lang-de) [lang="de"] {
display: none !important;
}
/* --- Modern Glassmorphic Language Selector --- */
.lang-select-container {
position: relative;
display: inline-flex;
align-items: center;
gap: 8px;
background: oklch(0.27 0.035 130 / 0.4);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 9999px;
/* No own padding: the <select> carries it, so the button (and its
focus/hover highlight in appearance:base-select) fills the whole pill
instead of only the inner ~110px. */
padding: 0;
overflow: hidden;
transition: background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), color 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1);
color: var(--text-muted);
}
.lang-select-container:hover {
background: oklch(0.27 0.035 130 / 0.6);
border-color: oklch(0.68 0.13 150 / 0.3);
color: var(--text);
box-shadow: 0 0 15px oklch(0.68 0.13 150 / 0.1);
}
.lang-select-container .globe-icon {
width: 16px;
height: 16px;
flex-shrink: 0;
opacity: 0.8;
transition: transform 0.5s ease;
}
.lang-select-container:hover .globe-icon {
transform: rotate(15deg);
opacity: 1;
}
.lang-select-container .chevron-icon {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
width: 12px;
height: 12px;
pointer-events: none;
opacity: 0.6;
}
.lang-select-container:hover .chevron-icon {
opacity: 1;
}
.lang-dropdown {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background: transparent;
border: none;
outline: none;
font-family: inherit;
font-size: 0.8rem;
font-weight: 600;
color: currentColor;
cursor: pointer;
/* Padding moved here from the container so the control fills the pill. */
padding: 6px 32px 6px 14px;
margin: 0;
width: auto;
min-width: 110px;
overflow: hidden;
border-radius: inherit;
}
@supports (appearance: base-select) {
.lang-dropdown::picker(select) {
appearance: base-select;
background-color: oklch(0.20 0.025 140);
border: 1px solid oklch(0.32 0.03 125);
border-radius: 8px;
padding: 4px;
font-family: 'Twemoji Country Flags', inherit;
}
}
.lang-dropdown option {
background: oklch(0.20 0.025 140);
color: white;
font-family: inherit;
font-size: 0.9rem;
}
/* Light theme: the pill was designed on the dark glass recipe by day it
becomes frosted white so it sits in the same family as the buttons. */
html.theme-light .lang-select-container {
background: rgba(255, 255, 255, 0.6);
border-color: oklch(0.28 0.035 140 / 0.14);
}
html.theme-light .lang-select-container:hover {
background: rgba(255, 255, 255, 0.85);
border-color: oklch(0.56 0.13 150 / 0.35);
box-shadow: 0 0 15px oklch(0.56 0.13 150 / 0.12);
}
html.theme-light .lang-dropdown option {
background: #ffffff;
color: oklch(0.21 0.03 140);
}
@supports (appearance: base-select) {
html.theme-light .lang-dropdown::picker(select) {
background-color: #ffffff;
border-color: oklch(0.28 0.035 140 / 0.18);
}
}
/* --- Hamburger Menu --- */
.hamburger {
display: none;
align-items: center;
justify-content: center;
background: none;
border: none;
color: var(--text);
font-size: 1.5rem;
cursor: pointer;
padding: 0.25rem;
line-height: 1;
}
/* --- Feature Cards: subtle differentiation --- */
.feature-card:nth-child(1) { --card-accent: oklch(0.68 0.13 150 / 0.06); }
.feature-card:nth-child(2) { --card-accent: oklch(0.62 0.14 45 / 0.06); }
.feature-card:nth-child(3) { --card-accent: oklch(0.68 0.13 150 / 0.06); }
.feature-card:nth-child(4) { --card-accent: oklch(0.75 0.10 150 / 0.06); }
.feature-card:nth-child(5) { --card-accent: oklch(0.68 0.14 45 / 0.06); }
.feature-card:nth-child(6) { --card-accent: oklch(0.62 0.14 45 / 0.06); }
.feature-card:nth-child(7) { --card-accent: oklch(0.62 0.14 45 / 0.06); }
.feature-card:nth-child(8) { --card-accent: oklch(0.68 0.13 150 / 0.06); }
.feature-card {
background: linear-gradient(135deg, var(--card-accent, transparent), oklch(0.27 0.035 130 / 0.45));
}
/* --- Compatibility Section --- */
.compat-section {
padding: 0.5rem 0 2.5rem 0;
text-align: center;
background: transparent;
border-bottom: 0;
}
.compat-mascot {
display: block;
margin: 0 auto 0.3rem auto;
max-width: 270px;
width: 100%;
height: auto;
}
.compat-heading {
font-size: 1rem;
font-weight: 600;
color: var(--text-muted);
letter-spacing: 0.08em;
text-transform: uppercase;
margin-bottom: 1.4rem;
}
.compat-row {
display: flex;
justify-content: center;
align-items: center;
gap: 2.4rem 3rem;
flex-wrap: wrap;
}
.compat-logo {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
font-size: 0.75rem;
font-weight: 700;
color: var(--text-muted);
transition: opacity 0.3s;
opacity: 0.55;
}
.compat-logo:hover {
opacity: 0.85;
}
.compat-logo img {
width: 28px;
height: 28px;
display: block;
}
.compat-logo img.compat-logo-wide {
width: 52px;
height: 28px;
object-fit: contain;
}
.compat-logo img.compat-logo-disneyplus-mark {
width: 60px;
height: 30px;
object-fit: contain;
filter: brightness(0) saturate(100%) invert(63%) sepia(12%) saturate(621%) hue-rotate(203deg) brightness(92%) contrast(88%);
}
html.theme-light .compat-logo img.compat-logo-disneyplus-mark {
filter: none;
}
@media (max-width: 700px) {
.compat-section {
padding: 0 0 1.6rem;
}
.compat-mascot {
max-width: 220px;
margin-bottom: 0.1rem;
}
.compat-heading {
font-size: 0.92rem;
line-height: 1.55;
margin-bottom: 1rem;
}
.compat-row {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1.55rem 0.75rem;
align-items: start;
}
.compat-logo {
gap: 0.35rem;
font-size: 0.72rem;
}
.compat-logo img {
width: 26px;
height: 26px;
}
.compat-logo img.compat-logo-wide {
width: 48px;
height: 26px;
}
.compat-logo img.compat-logo-disneyplus-mark {
width: 56px;
height: 28px;
}
.compat-logo-jellyfin {
display: none;
}
.compat-more {
grid-column: 1 / -1;
justify-self: center;
white-space: nowrap;
}
}
.compat-more {
opacity: 0.4;
cursor: help;
flex-direction: row;
gap: 0.35rem;
position: relative;
}
.compat-more:hover {
opacity: 0.6;
}
.compat-more-icon {
font-size: 1.1rem;
font-weight: 700;
color: var(--accent);
line-height: 1;
}
.compat-tooltip {
display: none;
position: absolute;
bottom: calc(100% + 10px);
left: 50%;
transform: translateX(-50%);
background: var(--card);
color: var(--text-muted);
padding: 0.6rem 0.9rem;
border-radius: 8px;
font-size: 0.72rem;
font-weight: 500;
white-space: nowrap;
border: 1px solid var(--glass-border);
box-shadow: 0 8px 20px rgba(0,0,0,0.4);
z-index: 10;
line-height: 1.4;
}
.compat-tooltip::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: var(--glass-border);
}
.compat-more:hover .compat-tooltip {
display: block;
}
+213
View File
@@ -0,0 +1,213 @@
/* --- Section collapse (FAQ, self-hosting): closed by default to keep the page short --- */
.section-collapse {
margin: 0 auto;
}
.faq-section-collapse {
max-width: 800px;
}
.collapse-summary {
display: flex;
align-items: center;
justify-content: center;
gap: 0.6rem;
list-style: none;
cursor: pointer;
font-weight: 700;
font-size: 1rem;
color: var(--accent);
background: oklch(0.68 0.13 150 / 0.08);
border: 1px solid oklch(0.68 0.13 150 / 0.3);
border-radius: 99px;
padding: 0.85rem 2rem;
max-width: 360px;
margin: 0 auto;
transition: background 0.3s, box-shadow 0.3s, transform 0.3s;
}
.collapse-summary::-webkit-details-marker {
display: none;
}
.collapse-summary:hover {
background: oklch(0.68 0.13 150 / 0.16);
box-shadow: 0 0 20px oklch(0.68 0.13 150 / 0.25);
transform: translateY(-2px);
}
.collapse-summary .collapse-chevron {
flex-shrink: 0;
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.section-collapse[open] .collapse-chevron {
transform: rotate(180deg);
}
.collapse-label-hide { display: none; }
.section-collapse[open] .collapse-label-show { display: none; }
.section-collapse[open] .collapse-label-hide { display: inline; }
.section-collapse[open] .collapse-summary {
margin-bottom: 2rem;
}
.section-collapse[open] .collapse-content {
animation: collapse-content-in 0.4s ease-out;
}
@keyframes collapse-content-in {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
.section-collapse[open] .collapse-content {
animation: none;
}
}
/* --- FAQ Section --- */
.faq-grid {
display: flex;
flex-direction: column;
gap: 1rem;
max-width: 800px;
margin: 0 auto;
}
.faq-item {
background: oklch(0.27 0.035 130 / 0.45);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 16px;
padding: 1.5rem 2rem;
cursor: pointer;
transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
overflow: hidden;
}
.faq-item:hover {
border-color: oklch(0.68 0.13 150 / 0.3);
box-shadow: 0 8px 20px oklch(0.68 0.13 150 / 0.1);
}
.faq-item[open] {
border-color: oklch(0.68 0.13 150 / 0.4);
background: oklch(0.27 0.035 130 / 0.65);
}
.faq-item summary {
font-weight: 700;
font-size: 1.05rem;
color: var(--text);
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
}
.faq-item summary::-webkit-details-marker {
display: none;
}
.faq-item summary::after {
content: '+';
font-size: 1.4rem;
color: var(--accent);
font-weight: 300;
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
flex-shrink: 0;
transform-origin: center;
}
.faq-item[open] summary::after {
transform: rotate(45deg);
}
.faq-item p {
color: var(--text-muted);
font-size: 0.95rem;
line-height: 1.6;
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid rgba(255, 255, 255, 0.06);
}
/* --- Focus states for interactive cards --- */
.feature-card:focus-visible,
.use-case-card:focus-visible,
.compat-logo:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 4px;
transform: translateY(-5px);
}
.feature-card,
.use-case-card,
.compat-logo,
section[id],
header[id] {
scroll-margin-top: 100px;
}
/* --- Screen-reader-only (also crawlable by search engines) --- */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* --- Skip-to-content accessibility link --- */
.skip-link {
position: absolute;
left: -9999px;
top: 0;
background: var(--accent);
color: var(--text-on-green);
padding: 0.75rem 1.25rem;
border-radius: 0 0 8px 0;
font-weight: 700;
z-index: 9999;
text-decoration: none;
}
.skip-link:focus {
left: 0;
}
/* --- Reduced motion support --- */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
.join-status-pulse { animation: none; }
.status-ring.active-pulse { animation: none; }
}
/* --- will-change hints for animated elements --- */
.join-status-pulse,
.status-ring.active-pulse,
.hero-mockup-wrapper,
.cta-group .btn {
will-change: transform, opacity;
}
@media (prefers-reduced-motion: reduce) {
.join-status-pulse,
.status-ring.active-pulse,
.hero-mockup-wrapper,
.cta-group .btn {
}
}
File diff suppressed because it is too large Load Diff
+461
View File
@@ -0,0 +1,461 @@
/* --- Use Cases / Anwendungsszenarien Section --- */
.use-cases-section {
padding: clamp(3.5rem, 6.5vh, 5rem) 0;
position: relative;
border-bottom: 0;
}
.use-cases-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 2rem;
margin-top: 1rem;
}
/* Sub-heading that separates the use-case scenarios from the feature tiles so
the two card types read as intentional groups (and gives the "Features" nav
link a real target). */
.section-subheading {
text-align: center;
font-size: 1.55rem;
font-weight: 800;
letter-spacing: -0.03em;
margin: 3.25rem 0 1.5rem;
scroll-margin-top: 96px;
}
.use-cases-feature-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
@media (max-width: 900px) {
.use-cases-feature-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1.25rem;
}
}
@media (max-width: 600px) {
.use-cases-feature-grid {
grid-template-columns: minmax(0, 1fr);
gap: 1rem;
}
}
.use-case-card {
background: oklch(0.27 0.035 130 / 0.4);
border: 1px solid var(--glass-border);
border-radius: 16px;
padding: 1.2rem 1.6rem 1.7rem 1.6rem;
text-align: left;
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.3s ease;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
display: flex;
flex-direction: column;
gap: 0.8rem;
position: relative;
overflow: hidden;
}
.use-case-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(90deg, transparent, var(--card-accent-border, var(--accent)), transparent);
opacity: 0;
transition: opacity 0.3s ease;
}
.use-case-card:nth-child(1) { --card-accent-border: oklch(0.68 0.13 150); }
.use-case-card:nth-child(2) { --card-accent-border: oklch(0.62 0.14 45); }
.use-case-card:nth-child(3) { --card-accent-border: oklch(0.75 0.10 150); }
/* Use-case cards are static content, not links no hover lift so they don't
read as clickable. The top accent bar (::before) stays visible instead. */
.use-case-card::before {
opacity: 1;
}
.use-case-image {
display: block;
width: 100%;
max-width: 272px;
height: 150px;
object-fit: contain;
border-radius: 8px;
margin: 0 auto 0 auto;
}
.cta-github-mascot {
display: block;
width: 100%;
max-width: 250px;
height: auto;
margin: 1.5rem auto;
}
/* Shared framing so the section mascots read as one set even though the
underlying illustrations differ slightly in style (a consistent, soft ground
shadow true art-direction alignment needs the assets themselves redrawn). */
.compat-mascot,
.features-questions-mascot,
.comparison-mascot,
.selfhost-mascot {
filter: drop-shadow(0 6px 14px oklch(0.15 0.02 145 / 0.22));
}
.features-questions-mascot {
display: block;
width: 100%;
max-width: 185px;
height: auto;
margin: -1rem auto 0.4rem auto;
}
.comparison-mascot {
display: block;
width: 100%;
max-width: 195px;
height: auto;
margin: -1.4rem auto 0.4rem auto;
}
.use-case-icon {
font-size: 1.6rem;
margin-right: 0.6rem;
display: inline-block;
vertical-align: middle;
filter: drop-shadow(0 2px 8px rgba(0,0,0,0.2));
}
.use-case-card h3 {
font-size: 1.25rem;
font-weight: 700;
margin: 0;
color: white;
}
.use-case-card p {
font-size: 0.9rem;
line-height: 1.6;
color: var(--text-muted);
margin: 0;
}
/* --- Comparison Section --- */
.comparison-section {
padding: clamp(3.5rem, 6.5vh, 5rem) 0;
background: transparent;
border-bottom: 0;
}
.comparison-table-wrapper {
overflow-x: auto;
background: oklch(0.27 0.035 130 / 0.35);
border: 1px solid var(--glass-border);
border-radius: 16px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
margin-top: 1rem;
}
.comparison-table {
width: 100%;
border-collapse: collapse;
text-align: left;
font-size: 0.95rem;
}
.comparison-table th,
.comparison-table td {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.comparison-table th {
background: oklch(0.20 0.025 140 / 0.6);
font-weight: 700;
color: white;
text-transform: uppercase;
font-size: 0.8rem;
letter-spacing: 0.08em;
}
.comparison-table th.highlight,
.comparison-table td.highlight {
background: oklch(0.68 0.13 150 / 0.08);
}
.comparison-table tbody tr:hover {
background: rgba(255, 255, 255, 0.02);
}
.comparison-table tbody tr:last-child td {
border-bottom: none;
}
.feat-name {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.feat-name strong {
color: white;
font-weight: 600;
}
.feat-desc {
font-size: 0.8rem;
color: var(--text-muted);
}
.check {
color: oklch(0.68 0.13 150);
font-weight: 700;
}
.cross {
color: oklch(0.68 0.17 25);
font-weight: 600;
opacity: 1;
}
@media (max-width: 768px) {
.comparison-table th,
.comparison-table td {
padding: 1rem;
font-size: 0.85rem;
}
}
/* On phones the 3-column table is turned into stacked cards so there is
no horizontal scrolling one card per feature, KoalaSync above Teleparty. */
@media (max-width: 600px) {
.comparison-table-wrapper {
overflow-x: visible;
background: transparent;
border: none;
box-shadow: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
margin-top: 0;
}
.comparison-table {
display: block;
font-size: 0.95rem;
}
/* Visually hide the header row but keep it for screen readers. */
.comparison-table thead {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.comparison-table tbody,
.comparison-table tr,
.comparison-table td {
display: block;
width: 100%;
}
.comparison-table tbody tr {
background: oklch(0.27 0.035 130 / 0.35);
border: 1px solid var(--glass-border);
border-radius: 14px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
margin-bottom: 1rem;
overflow: hidden;
}
.comparison-table tbody tr:last-child {
margin-bottom: 0;
}
.comparison-table td {
padding: 0.85rem 1.1rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.comparison-table tbody tr td:last-child {
border-bottom: none;
}
/* Feature name acts as the card header. */
.comparison-table td.feat-name {
background: oklch(0.20 0.025 140 / 0.55);
padding: 0.9rem 1.1rem;
}
/* Room is back on the card, so show the description again. */
.feat-desc {
display: block;
margin-top: 0.15rem;
}
/* Label each value cell with the product it belongs to. */
.comparison-table td.check,
.comparison-table td.cross {
display: flex;
align-items: baseline;
gap: 0.4rem;
}
.comparison-table td.check::before,
.comparison-table td.cross::before {
flex: 0 0 5.5rem;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--text-muted);
opacity: 0.85;
}
.comparison-table td.check::before,
.comparison-table td.cross::before {
content: attr(data-label);
}
/* Keep the KoalaSync row subtly highlighted, like on desktop. */
.comparison-table td.check.highlight {
background: oklch(0.68 0.13 150 / 0.08);
}
}
@media (max-width: 600px) {
html.theme-light .comparison-section {
background: transparent;
}
html.theme-light .comparison-table tbody tr {
background: #ffffff;
border-color: oklch(0.20 0.025 140 / 0.1);
box-shadow: 0 8px 20px oklch(0.20 0.025 140 / 0.08);
}
html.theme-light .comparison-table tbody tr:hover {
background: #ffffff;
}
html.theme-light .comparison-table td {
border-bottom-color: oklch(0.20 0.025 140 / 0.08);
}
html.theme-light .comparison-table td.feat-name {
background: #ffffff;
}
html.theme-light .comparison-table td.check.highlight {
background: oklch(0.52 0.12 150 / 0.07);
}
}
/* --- Footnotes & Source Links --- */
.source-link {
color: var(--accent);
text-decoration: none;
font-size: 0.72rem;
font-weight: 700;
margin-left: 0.25rem;
display: inline-flex;
align-items: center;
vertical-align: super;
opacity: 0.82;
transition: opacity 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
.source-link:hover {
opacity: 1;
color: oklch(0.75 0.10 150);
transform: translateY(-1px);
}
.table-footnotes {
padding: 0.8rem 1.25rem;
background: oklch(0.20 0.025 140 / 0.45);
border-top: 1px solid rgba(255, 255, 255, 0.05);
font-size: 0.72rem;
color: var(--text-muted);
line-height: 1.5;
opacity: 0.65;
transition: opacity 0.2s ease;
}
/* Link from the comparison table to the fuller guides/alternatives hub */
.comparison-guides-link {
text-align: center;
margin: 2rem 0 0;
}
.comparison-guides-link a {
display: inline-flex;
align-items: center;
gap: 0.45rem;
color: var(--accent);
text-decoration: none;
font-weight: 600;
font-size: 0.95rem;
transition: gap 0.2s ease, opacity 0.2s ease;
}
.comparison-guides-link a:hover {
gap: 0.7rem;
opacity: 0.85;
}
.table-footnotes:hover {
opacity: 0.95;
}
.table-footnotes p {
margin: 0;
display: flex;
align-items: baseline;
gap: 0.4rem;
}
.table-footnotes p:not(:last-child) {
margin-bottom: 0.4rem;
}
.table-footnotes a {
color: var(--accent);
text-decoration: none;
font-weight: 500;
transition: color 0.2s ease, text-decoration 0.2s ease;
}
.table-footnotes a:hover {
color: oklch(0.75 0.10 150);
text-decoration: underline;
}
.table-footnotes sup {
font-weight: 700;
color: var(--accent);
}
@media (max-width: 768px) {
.table-footnotes {
padding: 0.75rem 1rem;
font-size: 0.68rem;
}
}
+12
View File
@@ -0,0 +1,12 @@
.selfhost-mascot {
display: block;
width: 300px;
height: auto;
margin: 0 auto;
filter: drop-shadow(0 4px 12px rgba(0,0,0,0.15));
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.selfhost-mascot:hover {
transform: scale(1.05) translateY(-4px) rotate(-1deg);
}
+185
View File
@@ -0,0 +1,185 @@
/* --- Legal Pages --- */
.legal-content {
max-width: 800px;
margin: 8rem auto 4rem auto;
padding: 0 2rem;
}
.legal-card {
background: var(--card);
padding: 3rem;
border-radius: 24px;
border: 1px solid var(--glass-border);
}
.legal-card h1 {
font-size: 2.5rem;
margin-bottom: 2rem;
text-align: center;
}
.legal-card h2 {
font-size: 1.25rem;
margin-top: 1rem;
margin-bottom: 0.5rem;
color: var(--accent);
}
.legal-card p {
color: var(--text-muted);
margin-bottom: 0.5rem;
font-size: 0.95rem;
}
.legal-inline-link {
color: var(--accent);
text-decoration: underline;
text-underline-offset: 0.15em;
}
.legal-inline-label {
color: var(--text-muted);
}
/* Reset global section padding for legal sections specifically */
.legal-card section {
padding: 0 !important;
margin-bottom: 0.75rem;
}
/* --- Join Page Specifics --- */
.join-card {
max-width: 450px;
margin: 6rem auto;
text-align: center;
}
.room-badge {
display: inline-block;
background: oklch(0.68 0.13 150 / 0.1);
color: var(--accent);
padding: 0.5rem 1rem;
border-radius: 99px;
font-size: 0.8rem;
font-weight: 700;
margin-bottom: 1rem;
border: 1px solid oklch(0.68 0.13 150 / 0.2);
}
@media (max-width: 768px) {
.hero {
align-items: center;
padding-top: 5.5rem;
padding-bottom: 3.5rem;
min-height: 100svh;
}
.hero-grid {
min-height: auto;
}
.hero-grid {
grid-template-columns: minmax(0, 1fr);
text-align: center;
}
.step {
grid-template-columns: minmax(0, 1fr);
text-align: left;
}
.hero-text h1 {
font-size: 2.5rem;
max-width: none;
}
.cta-group {
justify-content: center;
flex-wrap: wrap;
}
.nav-links {
display: none;
position: absolute;
top: 100%;
left: 0;
right: 0;
flex-direction: column;
background: oklch(0.20 0.025 140 / 0.95);
backdrop-filter: blur(12px);
padding: 1rem 2rem;
gap: 1rem;
border-bottom: 1px solid var(--glass-border);
margin-left: 0;
}
.nav-links.open {
display: flex;
}
/* The dropdown panel is dark-green by default; in the light theme that
hard-coded colour clashed with the pale navbar and washed out the link
text. Match the panel and its links to the active theme instead. */
.nav-links a {
color: var(--text);
}
html.theme-light .nav-links {
background: oklch(0.95 0.01 100 / 0.97);
border-bottom-color: oklch(0.20 0.025 140 / 0.10);
}
.nav-right {
margin-left: auto;
}
.hamburger {
display: inline-flex !important;
}
nav .container {
padding: 0 0.5rem;
}
.logo-area {
gap: 0.25rem;
font-size: 1.1rem;
}
.logo-area img {
height: 40px;
width: 40px;
margin: 0;
}
.lang-select-container {
padding: 0;
gap: 4px;
}
.lang-select-container .globe-icon {
width: 14px;
height: 14px;
}
.lang-dropdown {
font-size: 0.7rem;
/* Padding on the control (not the container) so the highlight fills
the whole pill matches the desktop rule in landing-controls.css. */
padding: 4px 24px 4px 10px;
}
.lang-select-container .chevron-icon {
width: 10px;
height: 10px;
}
.legal-card {
padding: 1.5rem;
}
}
@media (min-width: 769px) and (max-height: 920px) {
.hero {
padding-top: clamp(6.5rem, 9vh, 8rem);
padding-bottom: clamp(2rem, 4vh, 3.5rem);
}
}
/* Extra-narrow phones: make sure logo, language picker and the menu button
never crowd each other in the header (kept comfortable down to ~320px). */
@media (max-width: 380px) {
nav .container {
padding: 0 0.4rem;
}
.nav-right {
gap: 0.35rem;
}
.logo-area {
font-size: 1rem;
gap: 0.4rem;
}
}

Some files were not shown because too many files have changed in this diff Show More