BWF官网中文

将BWF官网翻译成中文

// ==UserScript==
// @name         BWF官网中文
// @namespace    https://greasyfork.org/users/1384897
// @version      0.2
// @description  将BWF官网翻译成中文
// @author       ✌
// @match        https://bwf.tournamentsoftware.com/*
// @match        https://www.tournamentsoftware.com/*
// @require https://update.greasyfork.org/scripts/514165/1472911/%E4%BA%BA%E5%90%8D%E7%BB%B4%E6%8A%A4.js
// @grant        MIT
// ==/UserScript==

(function() {
    'use strict';

    const customDictionaryRegex = new RegExp(
        Array.from(customDictionary.keys()).map(key => key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'),
        'g'
    );

    const customNameDictionaryRegex = new RegExp(
        Array.from(customNameDictionary.keys()).map(key => `\\b${key}\\b`).join('|'),
        'gi'
    );

    // 月份映射表,将英文缩写映射到对应的月份数字
    const monthMapping = {
        "Jan": "1",
        "Feb": "2",
        "Mar": "3",
        "Apr": "4",
        "May": "5",
        "Jun": "6",
        "Jul": "7",
        "Aug": "8",
        "Sep": "9",
        "Oct": "10",
        "Nov": "11",
        "Dec": "12"
    };

    window.addEventListener('load', function() {
        replaceTextWithDictionaryAndFormatDates();
        formatDateInTimeTags(); // 格式化 <time> 标签中的日期
        formatComplexDatesInText();
        replaceSpecificText(); // 对特定文本进行替换

        // 使用 MutationObserver 监测 DOM 变化,确保动态加载内容也能被替换
        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.addedNodes.length > 0) {
                    replaceTextWithDictionaryAndFormatDates();
                    formatDateInTimeTags(); // 对新增的 <time> 标签内容进行格式化
                    formatComplexDatesInText();
                }
            });
        });

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

    function replaceTextWithDictionaryAndFormatDates() {
        const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
        let node;

        // 遍历文本节点并替换自定义词汇和日期格式
        while (node = walker.nextNode()) {
            let newText = replaceWithCustomNameDictionary(node.nodeValue);
            // 跳过 #PlayersView 内部的节点
            if (node.nodeValue.trim() && !isInsidePlayersView(node)) {
                newText = replaceWithCustomDictionary(newText);
            }
            newText = formatDateToChinese(newText); // 格式化日期
            node.nodeValue = newText;
        }
    }

    // 检查节点是否在 #PlayersView 内部
    function isInsidePlayersView(node) {
        let parent = node.parentNode;
        while (parent) {
            if (parent.id === 'PlayersView') {
                return true; // 节点在 #PlayersView 内部
            }
            parent = parent.parentNode;
        }
        return false;
    }

    // 批量替换函数
    function replaceWithCustomDictionary(text) {
        return text.replace(customDictionaryRegex, match => customDictionary.get(match) || match);
    }

    // 使用 Map 人名词汇表替换文本内容(大小写不敏感)
    function replaceWithCustomNameDictionary(text) {
        return text.replace(customNameDictionaryRegex, match => {
            const originalKey = Array.from(customNameDictionary.keys()).find(key =>
                key.toLowerCase() === match.toLowerCase()
            );
            return originalKey ? customNameDictionary.get(originalKey) : match;
        });
    }

    // 格式化普通文本中的日期,将 MM/DD/YYYY、MMM DD YYYY、MMM DD 至 MMM DD、MM月 DD 至 MM月 DD 格式转换为中文日期格式
    function formatDateToChinese(text) {
        // 处理 MM/DD/YYYY 格式
        text = text.replace(/\b(\d{1,2})\/(\d{1,2})\/(\d{4})\b/g, (match, month, day, year) => {
            return `${year}年${parseInt(month)}月${parseInt(day)}日`;
        });

        // 处理 MMM DD YYYY 格式
        text = text.replace(/\b([A-Za-z]{3}) (\d{1,2}) (\d{4})\b/g, (match, monthAbbr, day, year) => {
            const month = monthMapping[monthAbbr];
            return month ? `${year}年${month}月${parseInt(day)}日` : match;
        });

        // 处理 MMM DD 至 MMM DD 格式
        text = text.replace(/\b([A-Za-z]{3}) (\d{1,2}) 至 ([A-Za-z]{3}) (\d{1,2})\b/g, (match, startMonthAbbr, startDay, endMonthAbbr, endDay) => {
            const startMonth = monthMapping[startMonthAbbr];
            const endMonth = monthMapping[endMonthAbbr];
            if (startMonth && endMonth) {
                return `${startMonth}月${parseInt(startDay)}日 至 ${endMonth}月${parseInt(endDay)}日`;
            }
            return match;
        });

        // 处理 MM月 DD 至 MM月 DD 格式
        text = text.replace(/\b(\d{1,2})月 (\d{1,2}) 至 (\d{1,2})月 (\d{1,2})\b/g, (match, startMonth, startDay, endMonth, endDay) => {
            return `${startMonth}月${parseInt(startDay)}日 至 ${endMonth}月${parseInt(endDay)}日`;
        });

        return text;
    }

    // 格式化 <time> 标签中的日期,将 MM/DD/YYYY 和 MMM DD YYYY 格式转换为 YYYY年MM月DD日 格式
    function formatDateInTimeTags() {
        const timeTags = document.querySelectorAll('time');

        timeTags.forEach(timeTag => {
            const textContent = timeTag.textContent;

            // 检查 MM/DD/YYYY 格式的日期
            const mdYFormat = textContent.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
            if (mdYFormat) {
                const [ , month, day, year ] = mdYFormat;
                const formattedDate = `${year}年${parseInt(month)}月${parseInt(day)}日`;
                timeTag.textContent = formattedDate;
                timeTag.setAttribute('datetime', `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`);
                return;
            }

            // 检查 MMM DD YYYY 格式的日期
            const mmmDFormat = textContent.match(/^([A-Za-z]{3}) (\d{1,2}) (\d{4})$/);
            if (mmmDFormat) {
                const [ , monthAbbr, day, year ] = mmmDFormat;
                const month = monthMapping[monthAbbr];
                if (month) {
                    const formattedDate = `${year}年${month}月${parseInt(day)}日`;
                    timeTag.textContent = formattedDate;
                    timeTag.setAttribute('datetime', `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`);
                }
                return;
            }

            // 检查 MMM DD 至 MMM DD 格式的日期范围
            const mmmRangeFormat = textContent.match(/^([A-Za-z]{3}) (\d{1,2}) 至 ([A-Za-z]{3}) (\d{1,2})$/);
            if (mmmRangeFormat) {
                const [ , startMonthAbbr, startDay, endMonthAbbr, endDay ] = mmmRangeFormat;
                const startMonth = monthMapping[startMonthAbbr];
                const endMonth = monthMapping[endMonthAbbr];
                if (startMonth && endMonth) {
                    const formattedDate = `${startMonth}月${parseInt(startDay)}日 至 ${endMonth}月${parseInt(endDay)}日`;
                    timeTag.textContent = formattedDate;
                }
                return;
            }

            // 检查 MM月 DD 至 MM月 DD 格式的日期范围
            const chineseRangeFormat = textContent.match(/^(\d{1,2})月 (\d{1,2}) 至 (\d{1,2})月 (\d{1,2})$/);
            if (chineseRangeFormat) {
                const [ , startMonth, startDay, endMonth, endDay ] = chineseRangeFormat;
                const formattedDate = `${startMonth}月${parseInt(startDay)}日 至 ${endMonth}月${parseInt(endDay)}日`;
                timeTag.textContent = formattedDate;
            }
        });
    }

    // 处理复杂日期格式,替换 "Jul 17" 和 "October 25, 2024" 等格式
    function formatComplexDatesInText() {
        const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
        let node;

        while (node = walker.nextNode()) {
            if (node.nodeValue.trim()) {
                node.nodeValue = formatDateToChinese1(node.nodeValue);
            }
        }
    }

    // 格式化日期,将 "Jul 17" 或 "October 25, 2024" 格式替换为中文日期格式
    function formatDateToChinese1(text) {
        // 处理 "Jul 17" 格式,匹配类似 "Jul 17" 的短日期并替换为 "7月17日"
        text = text.replace(/\b([A-Za-z]{3}) (\d{1,2})\b/g, (match, monthAbbr, day) => {
            const month = monthMapping[monthAbbr];
            return month ? `${month}月${parseInt(day)}日` : match;
        });

        // 处理 "October 25, 2024" 格式,匹配类似 "October 25, 2024" 的完整日期并替换为 "2024年10月25日"
        text = text.replace(/\b([A-Za-z]{3,}) (\d{1,2}), (\d{4})\b/g, (match, monthName, day, year) => {
            const month = monthMapping[monthName.slice(0, 3)];
            return month ? `${year}年${month}月${parseInt(day)}日` : match;
        });

        return text;
    }

    // 处理特定元素中的文本
    function replaceSpecificText() {
        // 查找包含特定文本的 <p> 元素
        document.querySelectorAll('p.no-info').forEach(element => {
            if (element.innerHTML.includes('next to it.')) {
                // 替换文本内容
                element.innerHTML = element.innerHTML.replace('next to it.', '');
            }
        });
    }
})();