Greasy Fork

Greasy Fork is available in English.

Wplace 汉化插件

将网站 Wplace.live 的界面翻译成中文。

当前为 2025-08-19 提交的版本,查看 最新版本

// ==UserScript==
// @name         Wplace 汉化插件
// @namespace    http://tampermonkey.net/
// @version       0.1
// @description  将网站 Wplace.live 的界面翻译成中文。
// @author       Avava_Ava
// @match        https://wplace.live/*
// @license        MIT
// @run-at       document-body
// @icon         https://wplace.live/img/favicon-96x96.png
// ==/UserScript==

(function() {
    'use strict';

    // 创建一个翻译字典,将英文原文映射到中文译文
    const translations = {
        // ========== 页面标题与信息 ==========
        "Wplace - Paint the world": "Wplace - 描绘这世界",
        "Paint the world": "描绘这世界",
        "Wplace": "Wplace",
        "Feedback and bugs": "提供反馈或汇报问题",
        "Map powered by:": "地图技术由以下提供:",
        "©\n\t\t\t\t\t\tOpenMapTiles Data from \n": "OpenMapTiles 数据来自",
        "Overview": "概览",
        "How to paint faster": "如何画得快一些",
        "Hold": "按住",
        "and move your cursor over the map.": ",随后在地图上移动鼠标。",
        "My map is lagging": "我的地图画面卡顿严重",
        "Verify if": "(如果使用的是 Chrome 浏览器)请查看",
        "is enabled on": "选项是否开启。该选项位于 ",
        "Email:": "邮箱:",
        "Terms": "服务条款",
        "Privacy": "隐私政策",
        "Show profile": "显示个人资料",

         // ========== 文本 ==========
        "Paint pixel": "已放置的像素数",
        "Pixels painted:": "放置像素总数:",
        "Pixels": "放置像素总数",
        "painted": " ",
        "Region": "区域",
        "Pixels painted inside the region": "放置于该区域内像素的总数目",
        "Visit": "去看看",

        // ========== 按钮 & 提示 ==========
        "Info": "信息",
        "Zoom in": "放大",
        "Zoom out": "缩小",
        "Livestreams": "Twitch 相关直播",
        "Refresh": "刷新页面",
        "Toggle art opacity": "切换作品不透明度",
        "My location": "我的当前位置",
        "Paint": "绘制",
        "Close": "关闭",
        "Understood": "我明白了",
        "Store": "商店",
        "Move ↑": "移动至上方",
        "Move ↓": "移动至下方",
        "Eraser": "擦除",
        "Color Picker": "拾取像素颜色",
        "Offline": "您已离线",
        "Explore": "探索",
        "Favorite": "收藏",
        "Share": "分享",
        "Mute ": "禁用音效",
        "+2 max. charge/level": "每升一级,像素点储备上限+2",
        "Purchases": "支付信息",
        "Log Out": "退出登录",
        "Alliance": "联盟",

        // ========== 弹窗 & 标题 ==========
        "Max. Charges": "最大充能",
        "Welcome to": "欢迎来到",
        "Rules": "规则",
        "Important": "重要",
        "📑 Updated rules": "规则(已更新)",
        "Leaderboard": "排行榜",
        "PIX": "像素",
        "Location favorited": "已收藏该位置",
        "Location unfavorited": "已取消收藏该位置",
        "Share place": "分享该位置",
        "Image": "图像",
        "Copy": "复制",
        "Download": "下载",
        "No internet access or the servers are offline. Try again later.": "当前无网络连接,或本站服务器已离线。请稍后再试。",
        "Painted by:": "由该用户绘制:",
        "Username copied to clipboard": "已将用户名复制至剪贴板",
        "Zoom in to see the pixels": "放大地图即可看到像素点",

        // ========== 规则列表 ==========
        "😈 Do not paint over other artworks using random colors or patterns just to mess things up": "😈 禁止使用随机颜色或图案恶意涂抹他人的艺术作品",
        "🚫 No inappropriate content (+18, hate speech, innapropriate links, highly suggestive material, ...)": "🚫 禁止绘制不当内容(如成人内容、仇恨言论、不当链接、强暗示性内容等)",
        "🧑‍🤝‍🧑 Do not paint with more than one account": "🧑‍🤝‍🧑 禁止单人使用多个账户进行绘制",
        "🤖 Use of bots is not allowed": "🤖 禁止使用机器人",
        "🙅 Disclosing other's personal information is not allowed": "🙅 禁止泄露他人个人信息",
        "✅ Painting over other artworks to complement them or create a new drawing is allowed": "✅ 允许在他人作品上进行二次创作或绘制新图画",
        "✅ Griefing political party flags or portraits of politicians is allowed": "✅ 允许涂抹政党旗帜或政治人物肖像",
        "Violations of these rules may result in suspension of your account.": "违反上述规则可能会导致您的账户被封禁。",

        // ========== 排行榜 & 筛选 ==========
        "Regions": "地区",
        "Countries": "国家",
        "Players": "玩家",
        "Alliances": "联盟",
        "Today": "今日",
        "Week": "本周",
        "Month": "本月",
        "All time": "总计",

        // ========== 输入框 & 标签 ==========
        "Country": "国家",

        // ========== 商店页面 & 联盟页面 ==========
        "Droplets": "小液滴",
        "+5 Max. Charges": "像素点储备上限+5",
        "Increase your maximum paint charges capacity": "让你能够储备更多的像素",
        "+30 Paint Charges": "现有可用像素点立即+30",
        "Recharge paint charges": "恢复你的像素点储备",
        "MAX": "最大",
        "Profile": "个人资料",
        "Profile picture": "头像",
        "Add a new 16x16 profile picture": "新建一张大小为 16x16 的头像",
        "Flags": "旗帜",
        "Display your country’s flag next to your username. Plus, when painting in regions where you own the corresponding flag, you recover 10% of the charges spent.": "在自己的用户名一旁展示自己所属国家的旗帜。此外,在该旗帜对应国家境内进行绘制,你将恢复 10% 的既有像素点储备。",
        "Show more": "更多",
        "Show less": "收起",
        "Items": "购买项",
        "Get more charges": "让自己储备多一些像素点",
        "You gain 1 droplet per pixel painted and 500 droplets per level": "每绘制一个像素点,你将获得一颗小液滴;每升一级,你将获得 500 颗小液滴",
        "+0 bonus": "无赠送",
        "75,000 Droplets": "75000 颗小液滴",
        "+3,750 bonus": ",购买即多赠 3750 颗",
        "150,000 Droplets": "150000 颗小液滴",
        "+15,000 bonus": ",购买即多赠 15000 颗",
        "250,000 Droplets": "250000 颗小液滴",
        "+37,500 bonus": ",购买即多赠 37500 颗",
        "375,000 Droplets": "375000 颗小液滴",
        "+75,000 bonus": ",购买即多赠 75000 颗",
        "500,000 Droplets": "500000 颗小液滴",
        "+125,000 bonus": ",购买即多赠 125000 颗",
        "Members:": "成员总数:",
        "Headquarters:": "大本营坐标:",


        // 其他常见文本
        "Version": "当前版本",
        "Wplace is a collaborative, real-time pixel canvas layered over the world map, where anyone can paint and create art together.": "Wplace 是一片覆盖在世界地图图层之上的协作式实时像素画布,任何人都可以其上进行绘画,创作艺术。"
    };

    // 创建翻译函数
    function translateText(text) {
        return translations[text] || text;
    }

    // 翻译元素文本内容
    function translateElement(element) {
        if (!element || element.dataset.translated === 'true') return;

        // 处理文本节点
        if (element.nodeType === Node.TEXT_NODE) {
            const originalText = element.textContent.trim();
            if (originalText && translations[originalText]) {
                element.textContent = translations[originalText];
            }
            return;
        }

        // 处理元素节点
        if (element.nodeType === Node.ELEMENT_NODE) {
            // 翻译title属性
            if (element.title && translations[element.title]) {
                element.title = translations[element.title];
            }

            // 翻译aria-label属性
            if (element.getAttribute('aria-label') && translations[element.getAttribute('aria-label')]) {
                element.setAttribute('aria-label', translations[element.getAttribute('aria-label')]);
            }

            // 翻译placeholder属性
            if (element.placeholder && translations[element.placeholder]) {
                element.placeholder = translations[element.placeholder];
            }

            // 遍历子节点进行翻译
            Array.from(element.childNodes).forEach(child => {
                 if (child.nodeType === Node.TEXT_NODE) {
                    const originalText = child.textContent.trim();
                     if (originalText && translations[originalText]) {
                        child.textContent = child.textContent.replace(originalText, translations[originalText]);
                    }
                }
            });
        }
    }

    // 递归翻译所有子元素
    function translateAllElements(element) {
        if (!element || element.nodeType !== Node.ELEMENT_NODE) return;

        const walker = document.createTreeWalker(element, Node.ELEMENT_NODE | Node.TEXT_NODE);

        while(walker.nextNode()) {
            translateElement(walker.currentNode);
        }
    }

    // 观察DOM变化
    function observeChanges() {
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                // 处理新增节点
                mutation.addedNodes.forEach(node => {
                    translateAllElements(node);
                });

                // 处理属性变化
                if (mutation.type === 'attributes') {
                    translateElement(mutation.target);
                }

                // 处理文本变化
                if (mutation.type === 'characterData') {
                    translateElement(mutation.target.parentElement); // 翻译父元素以触发文本节点替换
                }
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: true,
            attributeFilter: ['title', 'aria-label', 'placeholder'],
            characterData: true
        });
    }

    // 翻译页面标题
    function translatePageTitle() {
        if (document.title && translations[document.title]) {
            document.title = translations[document.title];
        }
    }

    // 初始化函数
    function init() {
        translatePageTitle();
        translateAllElements(document.body);
        observeChanges();
        setInterval(translatePageTitle, 1000);
        console.log('Wplace 汉化插件已启动 (v1.1.0)');
    }

    // 翻译元数据
    function translateMeta() {
        document.querySelectorAll('meta[name="description"], meta[property^="og:"], meta[name^="twitter:"]').forEach(meta => {
            const content = meta.getAttribute('content');
            if (content && translations[content]) {
                meta.setAttribute('content', translations[content]);
            }
        });
    }

    // 启动插件
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => {
            init();
            translateMeta();
        });
    } else if (document.body) {
        init();
        translateMeta();
    } else {
        window.addEventListener('load', () => {
             init();
             translateMeta();
        });
    }
})();