Русификатор раздела по Майнкрафту на CurseForge.

Переводит на русский интерфейс раздела по Майнкрафту на CurseForge.

// ==UserScript==
// @name         Русификатор раздела по Майнкрафту на CurseForge.
// @namespace    http://tampermonkey.net/
// @version      1.8
// @license      MIT
// @description  Переводит на русский интерфейс раздела по Майнкрафту на CurseForge.
// @author       MrVovchick
// @match        https://www.curseforge.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const translations = {
        'Browse All': 'Посмотреть все',
        'Browse by': 'Искать по',
        'All': 'Все',
        'Shaders': 'Шейдеры',
        'Mods': 'Моды',
        'Modpacks': 'Модпаки',
        'Customization': 'Персонализация',
        'Addons': 'Аддоны',
        'Data Packs': 'Дата-паки',
        'Plugins': 'Плагины',
        'Resource Packs': 'Ресурс-паки',
        'Worlds': 'Миры',
        'Filters': 'Фильтры',
        'Mod Loaders': 'Загрузчики',
        'Game Version': 'Версия игры',
        'Game Versions': 'Версии игры',
        'Search for Minecraft mods': 'Поиск модов',
        'Sort by': 'Сортировать по',
        'Relevancy': 'Актуальности',
        'Popularity': 'Популярности',
        'Latest update': 'Последнему обновлению',
        'Creation Date': 'Дате создания',
        'Total Downloads': 'Количеству скачиваний',
        'Show per page': 'Показать на странице',
        'Projects found': 'Найдено проектов',
        'Minecraft Mods': 'Майнкрафт моды',
        'Minecraft Mods on CurseForge - The Home for the Best Minecraft Mods': 'Моды Minecraft на CurseForge - дом для лучших модов Minecraft',
        'Discover the best Minecraft Mods and Modpacks around.': 'Откройте для себя лучшие моды и модпаки для Minecraft.',
        'Minecraft is an action-adventure sandbox game where players can build pretty much anything they like, explore their surroundings, craft items, and even engage in combat.': 'Minecraft - это приключенческая игра-песочница, в которой игроки могут строить практически все, что им нравится, исследовать окружающую среду, создавать предметы и даже участвовать в боях.',
        'MC has one of the biggest modding communities in the world, and on this very page - you\'ll be able to become a part of it. If you\'ve been looking around some Minecraft forums recently, you probably know that this is the home for all the best Minecraft mods. Here, you\'ll be able to easily find and download the best Minecraft mods and modpacks around. From mods that change Minecraft\'s game interface, through mods that optimize its gameplay, or even mods that offer various tools for improved building, combating, or exploration.': 'MC - одно из самых больших моддинг-сообществ в мире, и на этой самой странице вы сможете стать его частью. Если вы недавно заглядывали на форумы по Minecraft, то наверняка знаете, что здесь собраны все лучшие моды для Minecraft. Здесь вы сможете легко найти и скачать лучшие моды и модпаки для Minecraft. От модов, изменяющих игровой интерфейс Minecraft, до модов, оптимизирующих игровой процесс, или даже модов, предлагающих различные инструменты для улучшения строительства, ведения боя или исследования.',
        'Browse through the selection of MC mods and modpacks, check out their descriptions and photos, and find out which ones are best for you.': 'Просмотрите подборку модов и модпаков MC, изучите их описания и фотографии и определите, какие из них подходят именно вам.',
        'Always keep in mind that each and every mod is completely free, so you can try them all until you find your favorite Minecraft mods and modpacks.': 'Не забывайте, что каждый мод совершенно бесплатен, поэтому вы можете пробовать их все, пока не найдете свои любимые моды и модпаки для Minecraft.',
        'And of course, the important thing is to have fun with these Minecraft mods - using them to create a personalized game experience that\'s best for you.': 'И конечно, главное - получать удовольствие от этих модов для Minecraft, используя их для создания индивидуального игрового опыта, который подходит именно вам.',
        'Read less': 'Читать меньше',
        'Read more': 'Читать больше',
        'projects': 'проектов',
        'Download': 'Скачать',
        'Install': 'Установить',
        'Description': 'Описание',
        'Files': 'Файлы',
        'Gallery': 'Галерея',
        'Relations': 'Отношения',
        'Source': 'Источник',
        'Issues': 'Вопросы',
        'Donate': 'Донат',
        'About Project': 'О проекте',
        'Created': 'Создано',
        'Updated': 'Обновлено',
        'Project ID': 'ID Проекта',
        'License': 'Лицензия',
        'View all': 'Смотреть все',
        'Versions': 'Версии',
        'Categories': 'Категории',
        'Main File': 'Основной файл',
        'Recent Files': 'Последние файлы',
        'Members': 'Участники',
        'Report': 'Репорт',
        'Show alpha files': 'Показать альфа-файлы',
        'This mod has no dependencies': 'Этот мод не имеет зависимостей',
        'All Relation types': 'Все типы отношений',
        'Embedded Library': 'Встроенная библиотека',
        'Optional Dependency': 'Необязательная зависимость',
        'Required Dependency': 'Необходимая зависимость',
        'Tool': 'Инструмент',
        'Incompatible': 'Несовместимость',
        'Include': 'Включите',
        'This mod has no gallery items available': 'У этого мода нет доступных элементов галереи',
        'Type': 'Тип',
        'Name': 'Имя',
        'Uploaded': 'Загружено',
        'Size': 'Размер',
        'Game Ver.': 'Вер. игры',
        'Downloads': 'Скачено',
        'Filter by': 'Фильтр по',
        'Clear all': 'Очистить все',
        'CurseForge - a world of endless gaming possibilities for modders and gamers alike.': 'CurseForge - мир бесконечных игровых возможностей для моддеров и геймеров.',
        'Download the best mods and addons!': 'Загружайте лучшие моды и аддоны!',
        'Download File': 'Скачать файл',
        'Dependencies': 'Зависимости',
        'Dependents': 'Больше информации',
        'STILL DOWNLOADING': 'ВСЕ ЕЩЕ ЗАГРУЖАЕТЕ',
        'MANUALLY??': 'ВРУЧНУЮ??',
        'Join over ': 'Присоединяйтесь к более чем ',
        '10 million players': '10 миллионам игроков,',
        'who use the': 'использующих',
        'CurseForge app!': 'приложение CurseForge!',
        'Download App Now': 'Скачать приложение сейчас',
        'If your download didn’t start, ': 'Если загрузка не началась, ',
        'try again': 'попробуйте снова',
        'Download file': 'Скачать файл',
        'Install with CurseForge app': 'Установить в приложении CurseForge',
        'File Details': 'Детали файла',
        'Back': 'Назад',
        'Supported Versions': 'Поддерживаемые версии',
        'Changelog': 'Изменения',
        'Additional Files': 'Дополнительные файлы',
        'Related Projects': 'Связанные проекты',
        'File Name': 'Имя файла',
        'Follow': 'Подписаться',
        'Favorite': 'Избранное',
        'Reason': 'Причина',
        'Spam': 'Спам',
        'Copyright Infringement': 'Нарушение авторских прав',
        'Lewd Content': 'Непристойное содержание',
        'Aggressive Behavior': 'Агрессивное поведение',
        'Malware/Virus': 'Вредоносные программы/вирусы',
        'Unsolicited Communication': 'Нежелательные сообщения',
        'Cancel': 'Отменить',
        'Submit': 'Отправить',
        'Discover': 'Открытия',
        'Browse all': 'Посмотреть все',
        'View': 'Посмотреть',
        'View Collection': 'Посмотреть коллекцию',
        'Tell me more': 'Расскажи мне больше',
        'Read Blog': 'Читать блог',
        'See Notes': 'Посмотреть заметки',
        'Latest Mods': 'Последние моды',
        'Popular Categories': 'Популярные категории',
        'Latest Modpacks': 'Последние модпаки',
        'Latest Resource Packs': 'Последние ресурс-паки',
        'Latest Worlds': 'Последние миры',
        'Popular Resource Packs': 'Популярные ресурс-паки',
        'Popular Modpacks': 'Популярные модпаки',
        'Popular Mods': 'Популярные моды',
        'Popular Worlds': 'Популярные миры',
        'Author': 'Автор',
        'Projects': 'Проекты',
        'Favorites': 'Избранное',
        'Followers': 'Подписчики',
        'Release Date': 'Дата выхода',
        'Message': 'Сообщение',
        'Games': 'Игры',
        'All games': 'Все игры',
        'Create': 'Создать',
        'Start a project': 'Начать проект',
        'Project submission guide': 'Руководство по представлению проектов',
        'Community': 'Сообщество',
        'Join Our Discord!': 'Присоединяйтесь к Discord!',
        'Support': 'Поддержка',
        'Companions': 'Компаньоны',
        'Comments': 'Коментарии',
        'Comment': 'Коментарий',
        'Post': 'Пост',
    };

    // Сортируем ключи по убыванию длины, чтобы длинные фразы обрабатывались раньше коротких
    const sortedTranslations = Object.entries(translations).sort((a, b) => b[0].length - a[0].length);

    // Функция для проверки границ слова
    function isWholeWord(text, word, index) {
        const before = index > 0 ? text[index - 1] : '';
        const after = index + word.length < text.length ? text[index + word.length] : '';
        const wordBoundaryRegex = /[^a-zA-Zа-яА-Я0-9]/;

        return (
            (index === 0 || wordBoundaryRegex.test(before)) &&
            (index + word.length === text.length || wordBoundaryRegex.test(after))
        );
    }

    function translateText(node) {
        // Обработка текстовых узлов
        if (node.nodeType === Node.TEXT_NODE) {
            let text = node.textContent;
            let newText = text;

            for (const [en, ru] of sortedTranslations) {
                const regex = new RegExp(en.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
                let match;

                while ((match = regex.exec(text)) !== null) {
                    if (isWholeWord(text, en, match.index)) {
                        newText = newText.substring(0, match.index) +
                                  ru +
                                  newText.substring(match.index + en.length);
                        regex.lastIndex = match.index + ru.length;
                    }
                }
                // Обновляем text после каждой замены, чтобы избежать наложений
                text = newText;
            }

            if (newText !== node.textContent) {
                node.textContent = newText;
            }
        }
        // Обработка элементов
        else if (node.nodeType === Node.ELEMENT_NODE) {
            // Обработка атрибутов title и placeholder
            ['title', 'placeholder'].forEach(attr => {
                if (node.hasAttribute(attr)) {
                    let value = node.getAttribute(attr);
                    let newValue = value;

                    for (const [en, ru] of sortedTranslations) {
                        const regex = new RegExp(en.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
                        let match;

                        while ((match = regex.exec(value)) !== null) {
                            if (isWholeWord(value, en, match.index)) {
                                newValue = newValue.substring(0, match.index) +
                                          ru +
                                          newValue.substring(match.index + en.length);
                                regex.lastIndex = match.index + ru.length;
                            }
                        }
                        value = newValue;
                    }

                    if (newValue !== node.getAttribute(attr)) {
                        node.setAttribute(attr, newValue);
                    }
                }
            });

            // Специальная обработка для заголовка
            if (node.classList && node.classList.contains('main-header')) {
                const spans = node.querySelectorAll('span');
                spans.forEach(span => {
                    let html = span.innerHTML;
                    let newHtml = html;

                    for (const [en, ru] of sortedTranslations) {
                        const regex = new RegExp(en.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
                        let match;

                        while ((match = regex.exec(html)) !== null) {
                            if (isWholeWord(html, en, match.index)) {
                                newHtml = newHtml.substring(0, match.index) +
                                          ru +
                                          newHtml.substring(match.index + en.length);
                                regex.lastIndex = match.index + ru.length;
                            }
                        }
                        html = newHtml;
                    }

                    if (newHtml !== span.innerHTML) {
                        span.innerHTML = newHtml;
                    }
                });
            }

            // Рекурсивная обработка дочерних элементов
            node.childNodes.forEach(translateText);
        }
    }

    function translateDocument() {
        translateText(document.body);

        // Специальная обработка для анимированного заголовка
        const header = document.querySelector('.main-header');
        if (header) {
            let html = header.innerHTML;
            let newHtml = html;

            for (const [en, ru] of sortedTranslations) {
                const regex = new RegExp(en.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
                let match;

                while ((match = regex.exec(html)) !== null) {
                    if (isWholeWord(html, en, match.index)) {
                        newHtml = newHtml.substring(0, match.index) +
                                  ru +
                                  newHtml.substring(match.index + en.length);
                        regex.lastIndex = match.index + ru.length;
                    }
                }
                html = newHtml;
            }

            if (newHtml !== header.innerHTML) {
                header.innerHTML = newHtml;
            }
        }
    }

    const observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            mutation.addedNodes.forEach(function(node) {
                if (node.nodeType === Node.ELEMENT_NODE) {
                    translateText(node);
                }
            });
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    // Запускаем перевод после небольшой задержки
    setTimeout(translateDocument, 1000);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址