// ==UserScript==
// @name Wplace 汉化插件
// @namespace http://tampermonkey.net/
// @version 0.2.5
// @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.": ",随后在地图上移动鼠标。",
"When painting, click on the button": "在绘制时,点击位于屏幕右上角上的",
"on the top right corner of the screen. This will lock the screen but it'll also enable painting by moving your finger 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": "联盟",
"Log in": "登录(不可用)",
// ========== 弹窗 & 标题 ==========
"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.": "当前无网络连接,或本站服务器已离线。请稍后再试。",
"You need zoom in to select a pixel": "进一步放大地图方可点选像素点",
"Painted by:": "由该用户绘制:",
"Username copied to clipboard": "已将用户名复制至剪贴板",
"Zoom in to see the pixels": "放大地图即可看到像素点",
"Logged out": "已退出登录(不可用)",
"Login with Google": "通过 Google 账号进行登录(不可用)",
"Login with Twitch": "通过 Twitch 账号进行登录(不可用)",
"By continuing, you agree to our": "继续操作,即表明您同意我们的",
"Terms of Service": "服务条款",
"and": "和",
"Privacy Policy": "隐私政策",
// ========== 规则列表 ==========
"😈 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();
});
}
})();