PageSourceSearch

https://topmacro.net/js/site-localization.js?v=20260905-1

js topmacro.net collected 2026-10-07 23:22:56 UTC 17,703 bytes, 281 lines download raw bytes

1'use strict';
2
3(function () {
4    var loginLabels = {
5        ru: 'Войти',
6        uk: 'Увійти',
7        en: 'Log in',
8        de: 'Anmelden',
9        es: 'Iniciar sesión',
10        'pt-br': 'Entrar',
11        fr: 'Connexion',
12        pl: 'Zaloguj się',
13        tr: 'Giriş',
14        it: 'Accedi',
15        ja: 'ログイン',
16        ko: '로그인',
17        zh: '登录',
18        'zh-hant': '登入'
19    };
20    var playerLabels = {
21        ru: ['Воспроизвести', 'Пауза', 'Назад на {seektime} с', 'Вперёд на {seektime} с', 'Перемотка', 'Громкость', 'Выключить звук', 'Включить звук', 'Настройки', 'Картинка в картинке', 'На весь экран', 'Выйти из полноэкранного режима', 'Скорость', 'Обычная', 'Повтор', 'Включено', 'Отключено', 'Включить субтитры', 'Выключить субтитры', 'Скачать', 'Вернуться в предыдущее меню'],
22        uk: ['Відтворити', 'Пауза', 'Назад на {seektime} с', 'Уперед на {seektime} с', 'Перемотування', 'Гучність', 'Вимкнути звук', 'Увімкнути звук', 'Налаштування', 'Картинка в картинці', 'На весь екран', 'Вийти з повноекранного режиму', 'Швидкість', 'Звичайна', 'Повтор', 'Увімкнено', 'Вимкнено', 'Увімкнути субтитри', 'Вимкнути субтитри', 'Завантажити', 'Повернутися до попереднього меню'],
23        en: ['Play', 'Pause', 'Rewind {seektime}s', 'Forward {seektime}s', 'Seek', 'Volume', 'Mute', 'Unmute', 'Settings', 'Picture in Picture', 'Enter fullscreen', 'Exit fullscreen', 'Speed', 'Normal', 'Loop', 'Enabled', 'Disabled', 'Enable captions', 'Disable captions', 'Download', 'Go back to previous menu'],
24        de: ['Wiedergabe', 'Pause', '{seektime} s zurück', '{seektime} s vor', 'Spulen', 'Lautstärke', 'Stummschalten', 'Ton einschalten', 'Einstellungen', 'Bild-in-Bild', 'Vollbildmodus', 'Vollbildmodus beenden', 'Geschwindigkeit', 'Normal', 'Wiederholen', 'Aktiviert', 'Deaktiviert', 'Untertitel einschalten', 'Untertitel ausschalten', 'Herunterladen', 'Zum vorherigen Menü zurückkehren'],
25        es: ['Reproducir', 'Pausa', 'Retroceder {seektime} s', 'Avanzar {seektime} s', 'Buscar', 'Volumen', 'Silenciar', 'Activar sonido', 'Ajustes', 'Imagen en imagen', 'Pantalla completa', 'Salir de pantalla completa', 'Velocidad', 'Normal', 'Repetir', 'Activado', 'Desactivado', 'Activar subtítulos', 'Desactivar subtítulos', 'Descargar', 'Volver al menú anterior'],
26        'pt-br': ['Reproduzir', 'Pausar', 'Voltar {seektime} s', 'Avançar {seektime} s', 'Buscar', 'Volume', 'Silenciar', 'Ativar som', 'Configurações', 'Imagem em imagem', 'Tela cheia', 'Sair da tela cheia', 'Velocidade', 'Normal', 'Repetir', 'Ativado', 'Desativado', 'Ativar legendas', 'Desativar legendas', 'Baixar', 'Voltar ao menu anterior'],
27        fr: ['Lire', 'Pause', 'Reculer de {seektime} s', 'Avancer de {seektime} s', 'Rechercher', 'Volume', 'Couper le son', 'Réactiver le son', 'Paramètres', 'Image dans l’image', 'Plein écran', 'Quitter le plein écran', 'Vitesse', 'Normale', 'Boucle', 'Activé', 'Désactivé', 'Activer les sous-titres', 'Désactiver les sous-titres', 'Télécharger', 'Revenir au menu précédent'],
28        pl: ['Odtwórz', 'Pauza', 'Cofnij o {seektime} s', 'Przewiń do przodu o {seektime} s', 'Przewiń', 'Głośność', 'Wycisz', 'Włącz dźwięk', 'Ustawienia', 'Obraz w obrazie', 'Pełny ekran', 'Opuść pełny ekran', 'Prędkość', 'Normalna', 'Pętla', 'Włączone', 'Wyłączone', 'Włącz napisy', 'Wyłącz napisy', 'Pobierz', 'Wróć do poprzedniego menu'],
29        tr: ['Oynat', 'Duraklat', '{seektime} sn geri', '{seektime} sn ileri', 'İlerleme', 'Ses düzeyi', 'Sesi kapat', 'Sesi aç', 'Ayarlar', 'Resim içinde resim', 'Tam ekran', 'Tam ekrandan çık', 'Hız', 'Normal', 'Döngü', 'Etkin', 'Devre dışı', 'Altyazıları aç', 'Altyazıları kapat', 'İndir', 'Önceki menüye dön'],
30        it: ['Riproduci', 'Pausa', 'Indietro di {seektime} s', 'Avanti di {seektime} s', 'Cerca', 'Volume', 'Disattiva audio', 'Attiva audio', 'Impostazioni', 'Immagine nell’immagine', 'Schermo intero', 'Esci da schermo intero', 'Velocità', 'Normale', 'Ripeti', 'Attivato', 'Disattivato', 'Attiva sottotitoli', 'Disattiva sottotitoli', 'Scarica', 'Torna al menu precedente'],
31        ja: ['再生', '一時停止', '{seektime}秒戻る', '{seektime}秒進む', 'シーク', '音量', 'ミュート', 'ミュート解除', '設定', 'ピクチャーインピクチャー', '全画面表示', '全画面表示を終了', '再生速度', '標準', 'ループ', '有効', '無効', '字幕を有効にする', '字幕を無効にする', 'ダウンロード', '前のメニューに戻る'],
32        ko: ['재생', '일시정지', '{seektime}초 뒤로', '{seektime}초 앞으로', '탐색', '볼륨', '음소거', '음소거 해제', '설정', '화면 속 화면', '전체 화면', '전체 화면 종료', '재생 속ë
32„', '보통', '반복', '사용', '사용 안 함', '자막 켜기', '자막 끄기', '다운로드', '이전 메뉴로 돌아가기'],
33        zh: ['播放', '暂停', '后退 {seektime} 秒', '前进 {seektime} 秒', '跳转', '音量', '静音', '取消静音', '设置', '画中画', '全屏', '退出全屏', '速度', '正常', '循环', '已启用', '已禁用', '启用字幕', '禁用字幕', '下载', '返回上一级菜单'],
34        'zh-hant': ['播放', '暫停', '後退 {seektime} 秒', '前進 {seektime} 秒', '跳轉', '音量', '靜音', '取消靜音', '設定', '子母畫面', '全螢幕', '退出全螢幕', '速度', '正常', '循環', '已啟用', '已停用', '啟用字幕', '停用字幕', '下載', '返回上一層選單']
35    };
36
37    function currentLocale() {
38        var segment = (window.location.pathname || '').replace(/^\/+/, '').split('/')[0].toLowerCase();
39        var htmlLang = (document.documentElement.lang || '').toLowerCase();
40
41        if (segment === 'ua') return 'uk';
42        if (segment === 'pt-br' || segment === 'zh-hant' || playerLabels[segment]) return segment;
43        if (htmlLang === 'uk') return 'uk';
44        if (htmlLang === 'pt-br') return 'pt-br';
45        if (htmlLang === 'zh-hant') return 'zh-hant';
46        if (playerLabels[htmlLang]) return htmlLang;
47
48        return 'ru';
49    }
50
51    function setText(element, value) {
52        if (element && element.textContent !== value) element.textContent = value;
53    }
54
55    function setAttribute(element, name, value) {
56        if (element && element.getAttribute(name) !== value) element.setAttribute(name, value);
57    }
58
59    function setLeadingText(element, value) {
60        if (!element) return;
61        for (var i = 0; i < element.childNodes.length; i++) {
62            if (element.childNodes[i].nodeType === 3) {
63                if (element.childNodes[i].nodeValue !== value) element.childNodes[i].nodeValue = value;
64                return;
65            }
66        }
67        element.insertBefore(document.createTextNode(value), element.firstChild);
68    }
69
70    function localizeAccountLinks(root) {
71        var value = loginLabels[currentLocale()] || loginLabels.en;
72        Array.prototype.forEach.call((root || document).querySelectorAll('.tm-account-link'), function (link) {
73            setText(link.querySelector('.tm-account-link__label'), value);
74            setAttribute(link, 'aria-label', value);
75            setAttribute(link, 'title', value);
76        });
77    }
78
79    function initStableVideoJumps() {
80        var selectors = [
81            '.bloody-watch-btn',
82            '.b7-watch-btn',
83            '.logitech-watch-btn',
84            '.synapse-watch-btn',
85            '.x7-watch-btn'
86        ];
87
88        document.addEventListener('click', function (event) {
89            var link = event.target.closest ? event.target.closest(selectors.join(',')) : null;
90            if (!link) return;
91
92            var href = link.getAttribute('href') || '';
93            if (href.charAt(0) !== '#') return;
94
95            var target = document.getElementById(href.slice(1));
96            if (!target) return;
97
98            var cancelled = false;
99            var events = ['wheel', 'touchstart', 'pointerdown', 'keydown'];
100            var pendingImages = Array.prototype.filter.call(document.images, function (image) {
101                return !image.complete && (image.compareDocumentPosition(target) & Node.DOCUMENT_POSITION_FOLLOWING);
102            });
103            var timers = [];
104            var cleanup = function () {
105                events.forEach(function (eventName) {
106                    window.removeEventListener(eventName, cancel, false);
107                });
108                pendingImages.forEach(function (image) {
109                    image.removeEventListener('load', align, false);
110                    image.removeEventListener('error', align, false);
111                });
112                timers.forEach(function (timer) { window.clearTimeout(timer); });
113            };
114            var cancel = function () {
115                cancelled = true;
116                if (window.jQuery) window.jQuery('html, body').stop(true);
117                cleanup();
118            };
119            var align = function () {
120                if (cancelled || !target.isConnected) return;
121                window.scrollTo(0, Math.max(0, target.getBoundingClientRect().top + window.pageYOffset - 63));
122            };
123
124            events.forEach(function (eventName) {
125                window.addEventListener(eventName, cancel, { once: true, passive: true });
126            });
127            pendingImages.forEach(function (image) {
128                image.addEventListener('load', align, { once: true });
129                image.addEventListener('error', align, { once: true });
130            });
131
132            timers.push(window.setTimeout(align, 900));
133            timers.push(window.setTimeout(align, 1800));
134            timers.push(window.setTimeout(align, 3000));
135            timers.push(window.setTimeout(cleanup, 3600));
136        }, true);
137    }
138
139    function localizePlayer(player, values) {
140        var play = player.querySelector('[data-plyr="play"]');
141        var mute = player.querySelector('[data-plyr="mute"]');
142        var fullscreen = player.querySelector('[data-plyr="fullscreen"]');
143        var rewind = player.querySelector('[data-plyr="rewind"]');
144        var fastForward = player.querySelector('[data-plyr="fast-forward"]');
145        var pip = player.querySelector('[data-plyr="pip"]');
146        var captions = player.querySelector('[data-plyr="captions"]');
147        var download = player.querySelector('[data-plyr="download"]');
148        var seekTimeMatch = ((rewind && rewind.textContent) || (fastForward && fastForward.textContent) || '').match(/\d+/);
149        var seekTime = seekTimeMatch ? seekTimeMatch[0] : '10';
150
151        if (play) {
152            setText(play.querySelector('.label--pressed'), values[1]);
153            setText(play.querySelector('.label--not-pressed'), values[0]);
154            setAttribute(play, 'aria-label', play.getAttribute('aria-pressed') === 'true' ? values[1] : values[0]);
155        }
156        if (mute) {
157            setText(mute.querySelector('.label--pressed'), values[7]);
158            setText(mute.querySelector('.label--not-pressed'), values[6]);
159            setAttribute(mute, 'aria-label', mute.getAttribute('aria-pressed') === 'true' ? values[7] : values[6]);
160        }
161        if (fullscreen) {
162            setText(fullscreen.querySelector('.label--pressed'), values[11]);
163            setText(fullscreen.querySelector('.label--not-pressed'), values[10]);
164            setAttribute(fullscreen, 'aria-label', fullscreen.getAttribute('aria-pressed') === 'true' ? values[11] : values[10]);
165        }
166        if (rewind) setText(rewind.querySelector('.plyr__sr-only'), values[2].replace('{seektime}', seekTime));
167        if (fastForward) setText(fastForward.querySelector('.plyr__sr-only'), values[3].replace('{seektime}', seekTime));
168        if (pip) {
169            setText(pip.querySelector('.plyr__sr-only'), values[9]);
170            setAttribute(pip, 'aria-label', values[9]);
171        }
172        if (captions) {
173            setText(captions.querySelector('.label--pressed'), values[18]);
174            setText(captions.querySelector('.label--not-pressed'), values[17]);
175            setAttribute(captions, 'aria-label', captions.getAttribute('aria-pressed') === 'true' ? values[18] : values[17]);
176        }
177        if (download) {
178            setText(download.querySelector('.plyr__sr-only'), values[19]);
179            setAttribute(download, 'aria-label', values[19]);
180        }
181
182        Array.prototype.forEach.call(player.querySelectorAll('[data-plyr="seek"]'), function (control) {
183            setAttribute(control, 'aria-label', values[4]);
184        });
185        Array.prototype.forEach.call(player.querySelectorAll('[data-plyr="volume"]'), function (control) {
186            setAttribute(control, 'aria-label', values[5]);
187        });
188        Array.prototype.forEach.call(player.querySelectorAll('button[data-plyr="settings"]'), function (control) {
189            var wrapper = control.firstElementChild && control.firstElementChild.tagName === 'SPAN' ? control.firstElementChild : null;
190            setText(control.querySelector('.plyr__sr-only'), values[8]);
191            setAttribute(control, 'aria-label', values[8]);
192            if (wrapper) {
193                var text = (wrapper.firstChild && wrapper.firstChild.nodeValue || '').trim().toLowerCase();
194                if (text === 'speed') setLeadingText(wrapper, values[12]);
195                if (text === 'loop') setLeadingText(wrapper, values[14]);
196                var menuValue = wrapper.querySelector('.plyr__menu__value');
197                if (menuValue && menuValue.textContent === 'Normal') setText(menuValue, values[13]);
198                if (menuValue && menuValue.textContent === 'undefined') setText(menuValue, values[16]);
199            }
200        });
201        Array.prototype.forEach.call(player.querySelectorAll('button[data-plyr="speed"]'), function (control) {
202            if (control.textContent.trim() === 'Normal') setText(control, values[13]);
203        });
204        Array.prototype.forEach.call(player.querySelectorAll('.plyr__control--back'), function (control) {
205            var sectionId = control.parentElement ? control.parentElement.id : '';
206            var sectionLabel = control.querySelector('[aria-hidden="true"]');
207
208            if (/-speed$/.test(sectionId)) setText(sectionLabel, values[12]);
209            if (/-loop$/.test(sectionId)) setText(sectionLabel, values[14]);
210            setText(control.querySelector('.plyr__sr-only'), values[20]);
211            setAttribute(control, 'aria-label', values[20]);
212        });
213    }
214
215    function initFallbackPlayerLocalization() {
216        if (window.tmSitePlyrLocalizationReady) return;
217        window.tmSitePlyrLocalizationReady = true;
218        window.tmPlyrLocalizationReady = true;
219
220        var values = playerLabels[currentLocale()] || playerLabels.en;
221        var pending = new Set();
222        var observed = new WeakSet();
223        var scheduled = false;
224        var queuePlayer = function (player) {
225            if (!player || !player.matches('.plyr')) return;
226            pending.add(player);
227            if (!observed.has(player) && window.MutationObserver) {
228                observed.add(player);
229                new MutationObserver(function () { queuePlayer(player); }).observe(player, {
230                    childList: true, subtree: true, attributes: true,
231                    attributeFilter: ['aria-label', 'aria-pressed']
232                });
233            }
234            if (scheduled) return;
235            scheduled = true;
236            window.setTimeout(function () {
237                scheduled = false;
238                var players = Array.from(pending);
239                pending.clear();
240                players.forEach(function (item) {
241                    if (item.isConnected) localizePlayer(item, values);
242                });
243            }, 0);
244        };
245        document.querySelectorAll('.plyr').forEach(queuePlayer);
246        ['ready', 'play', 'pause', 'volumechange', 'enterfullscreen', 'exitfullscreen', 'captionsenabled', 'captionsdisabled'].forEach(function (eventName) {
247            document.addEventListener(eventName, function (event) {
248                var target = event.target;
249                if (target && target.closest) queuePlayer(target.closest('.plyr'));
250            }, true);
251        });
252    }
253
254    function init() {
255        localizeAccountLinks();
256        initFallbackPlayerLocalization();
257        initStableVideoJumps();
258
259        window.setTimeout(localizeAccountLinks, 120);
260        window.setTimeout(localizeAccountLinks, 320);
261        if (window.MutationObserver) {
262            document.querySelectorAll('.navbar, .tm-account-topbar').forEach(function (root) {
263                var scheduled = false;
264                new MutationObserver(function () {
265                    if (scheduled) return;
266                    scheduled = true;
267                    window.setTimeout(function () {
268                        scheduled = false;
269                        localizeAccountLinks(root);
270                    }, 0);
271                }).observe(root, { childList: true, subtree: true });
272            });
273        }
274    }
275
276    if (document.readyState === 'loading') {
277        document.addEventListener('DOMContentLoaded', init);
278    } else {
279        init();
280    }
281}());

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.