您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
汉化 msu.io 等相关页面.
当前为
// ==UserScript== // @name 冒险岛N宇宙 MSU 网页汉化 // @namespace http://tampermonkey.net/ // @version 1.1.1 // @description 汉化 msu.io 等相关页面. // @author B站-放肆到底丶 // @homepageURL https://space.bilibili.com/430674 // @icon https://globalstatic.xangle.io/explorer/nexon/logo/logo_mainnet_mobile.png // @match https://msu.io/* // @match https://static.msu.io/inspection // @match https://msu-explorer.xangle.io/ // @match https://docs.maplestoryn.io/* // @license MIT // @grant none // ==/UserScript== (function() { 'use strict'; // 翻译状态控制 let isTranslationEnabled = localStorage.getItem('msu-translation-enabled') !== 'false'; // 保存翻译状态到localStorage function saveTranslationState(enabled) { localStorage.setItem('msu-translation-enabled', enabled); } // 数字格式化函数 function formatNumberToChinese(numStr) { const num = parseInt(numStr, 10); if (num >= 100000000) { return (num / 100000000).toFixed(0) + '亿'; } else if (num >= 10000) { return (num / 10000).toFixed(0) + '万'; } return numStr; } // 自定义翻译词典(用户可在此添加/修改翻译条目) const CUSTOM_DICT = { // https://msu.io/maplestoryn/ 'MapleStory N': '冒险岛N', 'Will start soon!': '即将开始!', 'Please wait for a moment.': '请稍等.', 'News': '新闻', 'New': '新', 'notices': '公告', 'Articles': '文章', 'update': '更新', 'Event': '活动', 'Guide': '指南', 'Classes & Jobs': '职业 & 转职', 'Main Stat': '主要属性', 'Weapons Used': '主要武器', 'Read more': '了解更多', 'All': '全部', 'Explorer': '冒险家', 'Warrior': '战士', 'Hero': '英雄', 'Paladin': '圣骑士', 'Dark Knight': '黑骑士', 'magician': '法师', 'Arch Mage': '魔导师', 'Fire/Poison': '火/毒', 'Arch Mage (Fire / Poison)': '魔导师(火/毒)', 'Ice/Lightning': '冰/雷', 'Arch Mage (Ice / Lightning)': '魔导师(冰/雷)', 'Bishop': '主教', 'bowman': '弓箭手', 'Bowmaster': '神射手', 'Marksman': '箭神', 'thief': '飞侠', 'Night Lord': '隐士', 'Shadower': '侠盗', 'pirate': '海盗', 'Buccaneer': '冲锋队长', 'Corsair': '船长', 'Job Advancement': '职业转职', 'Beginner': '新手', '1st Job': '一转', '2nd Job': '二转', '3rd Job': '三转', '4th Job': '四转', 'Beginner’s Guide': '新手上路', 'Download Guide': '下载中心', 'Game Status': '游戏状态', 'Ranking': '排名', 'PLAYER RANKING': '玩家排名', 'View More': '查看更多', 'Track your standing among fellow maplers and see who’s claimed the top spots.': '跟踪你在同服玩家中的排名,看看谁占据了顶尖位置。', 'Dynamic Pricing': '动态定价', 'Probability Info': '概率信息', 'Probability Information': '概率信息', 'All random outcomes for items and functions display clear probabilities, rounded to six decimal places.': '所有物品和功能的随机结果都显示明确的概率,四舍五入到小数点后六位。', 'Bonus Stat': '额外属性', 'Rank Increase Probability': '等级提升概率', 'Sort': '排序', 'Rank 1': '等级1', 'Rank 2': '等级2', 'Rank 3': '等级3', 'Rank 4': '等级4', 'Rank 5': '等级5', 'Powerful Rebirth Flame': '强大的涅槃火焰\nPowerful Rebirth Flame', 'Eternal Rebirth Flame': '永远的涅槃火焰\nEternal Rebirth Flame', 'Black Rebirth Flame': '宿命黑暗的涅槃火焰\nBlack Rebirth Flame', '* Boss equipment\'s final rank will be with a +2 rank bonus, and treated as rank 3 - 7.': '* BOSS装备的最终等级将带有+2等级加成,并视为3-7级。', 'Number of Options': '选项数量', // https://msu.io/maplestoryn/gamestatus/probabilityitems 'Equipment Category': '装备分类', 'Stat': '属性', 'STR': '力量', 'STR (Strength)': 'STR (力量)', 'DEX': '敏捷', 'DEX (Dexterity)': 'DEX (敏捷)', 'INT': '智力', 'INT (Intelligence)': 'INT (智力)', 'LUK': '幸运', 'LUK (Luck)': 'LUK (幸运)', 'STR+DEX': '力量+敏捷', 'STR+INT': '力量+智力', 'STR+LUK': '力量+幸运', 'DEX+INT': '敏捷+智力', 'DEX+LUK': '敏捷+幸运', 'INT+LUK': '智力+幸运', 'Max HP': '最大HP', 'Max MP': '最大MP', 'Reduced Level Requirement': '降低等级要求', 'DEF': '防御', 'ATT': '攻击', 'Magic ATT': '魔法攻击', 'DEF Ignored': '无视防御', 'Damage': '伤害', 'ALL Stats': '全部属性', 'Other Equipment': '其他装备', 'Movement Speed': '移动速度', 'Jump': '跳跃力', 'Marketplace': '市场', // https://msu.io/marketplace 'Connect your wallet and use the marketplace!': '连接你的钱包并使用市场!', 'Recommended Items': '推荐物品', 'Accessories Make the Build. Make Yours Count.': '饰品搭配,打造你的特色!', 'Fortify Your Journey with Unchained Armors!': '强化你的旅程,解放系列防具!', 'Accelerate Your Adventure with Unchained Weapons!': '使用 解放系列武器 加速你的冒险!', 'Your NFT Collection Grows With Every Step.': '你的 NFT 收藏随着每一步的进展而增长。', 'RECOMMENDED': '推荐', 'ITEMS': '物品', 'Hey!': '嗨!', 'How about this?': '试试这个?', 'Past 30 Days': '过去30天', 'Total Listings': '总列表', 'Total Active Wallets': '总活跃钱包', 'Total Sales': '总销售额', 'Total Trading volume': '总交易量', 'Sales': '销售额', 'Recent': '最近', 'Listings': '列表', 'Traders': '交易者', 'Type': '类型', 'Skill': '技能', 'Popular Searches': '热门搜索', // https://msu.io/marketplace/nft 'NFT Item': 'NFT 物品', 'No items owned.': '没有拥有的物品。', 'Game Play': '玩游戏', 'Due to the high volume of search results, only a portion is displayed.': '由于搜索结果过多,只显示部分。', 'Price: Low to High': '价格: 低到高', 'Price: High to Low': '价格: 高到低', 'Time: Ending Soon': '时间: 即将结束', 'Time: Newly Listed': '时间: 最新发布', 'Offer': '报价', 'Offers Received': '报价接收', 'Highest Offer': '最高报价', 'Offer(s)': '报价(个)', 'See Offers': '查看报价', 'Accept Offer': '接受报价', 'Offers Sent': '报价发送', 'View recent offers on your listings. Only the 5 highest offers are displayed, with updates if an offer is canceled, expires, or is accepted.': '查看你的列表中最近的报价。只显示前5个报价,报价取消、过期或接受时更新。', 'View all items you’ve placed offers on.': '查看你已发送报价的物品。', 'There is no price offer history yet.': '没有交易历史。', 'Price': '价格', 'Price must be greater than or equal to 0.000001 NESO.': '价格必须大于或等于 0.000001 NESO。', 'Expiration': '到期时间', 'From': '来自', 'Price Range': '价格范围', 'Unique Number': '唯一编号', 'Item Type': '物品类型', 'List for sale': '列入清单', 'Listing': '清单', 'Lowest Listed Price': '最低报价', 'Last Traded Price': '上次交易价格', '14-Day Price Range': '14天价格范围', 'No trade history': '没有交易历史', 'Duration': '持续时间', 'Description': '描述', 'In Progress': '进行中', 'Rejected': '已拒绝', 'The link has been copied!': '链接已复制!', 'Notifications': '通知', 'Account': '账号', 'Delete Individually': '逐个删除', 'Delete All': '全部删除', // NFT 物品词缀 'Weapon Type': '武器类型', 'Required Level': '所需等级', 'Attack Speed': '攻击速度', 'Normal(6)': '普通(6)', 'Knockback Chance': '直接攻击时击退几率', 'Boss Damage': '攻击首领怪时,伤害', 'Cannot Star Force Enhance': '无法使用星级强化', 'Cannot Set/Reset Bonus Stats': '无法设置/重置属性', 'Weapon': '武器', 'One-handed Weapon': '单手武器', 'One-handed Sword': '单手剑', 'One-handed Axe': '单手斧', 'One-handed Blunt Weapon': '单手钝器', 'Dagger': '短刀', 'Wand': '短仗', 'Staff': '长杖', 'Staff, Wand': '长杖, 短仗', 'Two-handed Weapon': '双手武器', 'Two-handed Sword': '双手剑', 'Two-handed Axe': '双手斧', 'Two-handed Blunt': '双手钝器', 'Spear': '枪', 'Polearm': '矛', 'Bow': '弓', 'Crossbow': '弩', 'Claw': '拳套', 'Knuckle': '指节', 'Gun': '短枪', 'One or Two Handed Swords or Axes': '单手剑, 双手剑, 单手斧, 双手斧', 'One or Two Handed Swords or Blunt Weapons': '单手剑, 双手剑, 单手钝器, 双手钝器', 'Spear, Polearm': '枪, 矛', 'Throwing Stars, Claw': '飞镖, 拳套', 'Secondary Weapon': '副手武器', 'Medal': '吊坠', 'Rosary': '念珠', 'Iron Chain': '铁链', 'Magic Book': '魔道书', 'Arrow Fletching': '箭羽', 'Bow Thimble': '扳指', 'Dagger Scabbard': '短剑剑鞘', 'Charm': '护身符', 'Wrist Band': '手腕护带', 'Far Sight': '瞄准器', 'Armor': '防具', 'Hat': '帽子', 'Top': '上衣', 'Outfit': '套装', 'Bottom': '下装', 'Shoes': '鞋子', 'Gloves': '手套', 'Cape': '披风', 'Accessory': '饰品', 'Face Accessory': '脸部饰品', 'Eye Accessory': '眼部饰品', 'Earrings': '耳环', 'Ring': '戒指', 'Pendant': '吊坠', 'Belt': '腰带', 'Shoulder Accessory': '肩部饰品', 'Pocket Item': '口袋物品', 'Badge': '徽章', 'Emblem': '纹章', 'Decoration': '装饰', 'Pet Equipment': '宠物装备', 'Beauty': '美容', 'Face': '脸部', 'Hair': '头发', 'Skin': '皮肤', 'Color': '颜色', 'Select Color': '选择颜色', 'Utility': '实用', 'Pet': '宠物', 'Expanded Auto Move': '扩大移动范围', 'Expanded Auto Move Skill': '扩大移动范围技能', 'Magnet Effect': '磁力效果', 'Magnet Effect Skill': '磁力效果技能', 'Auto Buff': '自动使用Buff', 'Auto Buff Skill': '自动使用Buff技能', 'Auto Move': '自动拾取', 'Auto Move Skill': '自动拾取技能', 'Fatten Up Skill': '增强技能', 'Pet Training Skill': '宠物训练技能', 'Multi Pet(Can use up to 3 pets at once)': '多宠物(一次最多使用3个)', // 宠物技能汉化 'Item Pouch': '捡取道具', 'NESO Magnet': '捡NESO', 'Fatten Up': '增强技能', 'Auto HP Potion Pouch': '自动服用 HP药水', 'Auto MP Potion Pouch': '自动服用 MP药水', 'Set-up': '配置', 'Chair': '椅子', 'Mount': '坐骑', 'Damage Skin': '伤害皮肤', 'Arrow, Throwing Stars, and Bullets': '箭, 飞镖和子弹', 'Arrow for Bow': '弓用箭矢', 'Arrow for Crossbow': '弩用箭矢', 'Throwing Stars': '飞镖', 'Bullets': '子弹', 'Class': '基础职业', 'Job': '职业', 'JOB DETAILS': '职业详情', 'Potential': '潜能', 'Bonus Potential': '额外潜能', 'None': '无', 'Rare': '稀有', 'Epic': '史诗', 'Unique': '罕见', 'Legendary' : '传说', 'Level Range': '等级范围', 'Star Force Enhancement': '星级强化', 'Search': '搜索', 'Reset': '重置', 'Save Filter': '保存筛选', 'Select the saved filter': '选择已保存的筛选', 'Done': '完成', 'The filter condition has been saved.': '筛选条件已保存。', 'Preview': '预览', 'Return to item image': '返回物品图片', 'History': '历史', 'There is no history to display.': '没有可显示的历史。', 'Name': '名称', 'Character': '角色', 'Date': '日期', 'Details': '详情', 'Circulating Supply': '流通供应量', 'Max Supply': '最大供应量', 'Token Standard': '代币标准', 'Day(s)': '天', // https://msu.io/marketplace/ft 'FT Item': 'FT 物品', 'Umushroom Coupon (100-Day)': '蘑菇卷 Umushroom Coupon (100天)', 'Red Florin': '红色弗林 Red Florin', 'Blue Florin': '蓝色弗林 Blue Florin', 'Green Florin': '绿色弗林 Green Florin', 'Mystic EXP Coupon Box': '神秘经验券盒 Mystic EXP Coupon Box', 'Mystic Honor Coupon Box': '神秘荣誉券盒 Mystic Honor Coupon Box', 'Vol.': '成交量', // https://msu.io/marketplace/character 'Exchange Currency': '交换货币', 'Voucher': '兑换券', 'By Highest Trading Volume': '按最高交易量排序', 'By Lowest Price': '按最低价格', 'By Highest Price': '按最高价格', 'By Highest Increase': '按最高涨幅排序', 'By Lowest Increase': '按最低涨幅排序', 'View My Items Only': '只查看我的物品', 'Normal': '普通', 'Your holdings': '你的持有', 'Floor price': '地板价格', 'Prev Day Avg Price': '昨日平均价', '24h Volume': '24小时交易量', '24h Volume(NESO)': '24小时交易量 (NESO)', 'Available Listings': '可用列表', 'There are no listings.': '没有列表。', 'Price (NESO)': '价格 (NESO)', 'Quantity': '数量', 'Buy': '购买', 'Buy Now': '立即购买', 'Available': '可用', 'The purchase quantity has changed due to the listing status.': '由于列表状态的变化,购买数量已更改。', 'Expected Price': '预期价格', 'Automaticallymatches youwithlistings thatcanbepurchased atthelowest price,afterpriceper itemandfees.Calculations exclude items you\'ve listed.': '自动为您匹配在扣除每件物品价格和手续费后可按最低价格购买的列表。计算时排除您已列出的物品。', 'Average Price per Item': '平均价格/件', 'You will pay': '你将支付', 'Sell': '出售', 'Enter Price per Item': '输入价格/件', 'Fee': '手续费', 'You will get': '你将获得', 'Trade History': '交易历史', 'Highest Price': '最高价格', 'Lowest Price': '最低价格', 'Average Price': '平均价格', 'Trading Volume': '交易量', 'Time': '时间', 'Price History': '价格历史', '- Highest Price': '- 最高价格', '- Lowest Price': '- 最低价格', '- Average Price': '- 平均价格', '- Trading Volume': '- 交易量', '3Day': '3天', '3 Day': '3天', '5Day': '5天', '5 Day': '5天', '7Day': '7天', '7 Day': '7天', '14Day': '14天', '14 Day': '14天', '30Day': '30天', '30 Day': '30天', 'Trading Volume(NESO)': '交易量 (NESO)', 'Average Price(NESO)': '平均价格 (NESO)', 'No trade history to display': '没有交易历史可显示', 'My Listings': '我的列表', 'All Items': '所有物品', 'Current Item': '当前物品', 'Log in to check your listings': '登录(不可用)以查看您的列表。', 'There is no active listings.': '没有活跃列表。', 'Characters': '角色', // https://msu.io/marketplace/bid 'Advanced Search (5)': '高级搜索 (5)', 'Select': '选择', 'Bid': '投标', // https://msu.io/marketplace/bid 'Watching': '关注', 'Bid Size: Large to Small': '投标大小: 从大到小', 'Bid Price: High to Low': '投标价格: 从高到低', 'Total Number of Bids': '总投标数', 'Highest Bid': '最高投标', 'All Bids': '所有投标', 'Place Bid': '投标', 'Bidder': '投标人', 'Price per Items': '价格/件', 'My Order': '我的订单', 'There is no active order.': '没有活跃订单。', 'Connect': '连接', 'Connect Wallet': '连接钱包', 'Connect your wallet to use MapleStory Universe!': '连接钱包即可使用 冒险岛宇宙!', 'Continue with': '继续使用', 'Inventory': '背包', 'Insufficient Balance': '余额不足', 'Logout': '登出', // https://msu.io/marketplace/inventory/ 'Owned': '拥有', 'On sale': '出售中', 'Cancellisting': '取消清单', 'Would you like to cancel the listing?': '您想取消列表吗?', 'No': '否', 'Yes': '是', 'Bookmark': '收藏夹', 'No items bookmarked yet.': '暂无收藏项目。', 'Explore Now': '立即探索', 'Activity': '活动', // https://msu.io/ 'My Page': '我的页面', 'Overview': '概览', 'Account Status': '账户状态', 'Verification': '验证', 'Today\'s withdrawal limit': '今日提现限额', 'Complete': '完成', 'ID verified': 'ID已验证', 'ID verification': 'ID验证', 'Withdrawal Limit': '提现限额', 'Social Account': '社交账号', 'Unlinked': '未绑定', 'Last Login': '最后登录(不可用)', 'View All': '查看全部', 'Total Item Minted': '总铸造物品数量', 'Total NESO Minted': '总铸造 NESO 数量', 'Total Trading volume (NESO)': '总交易量 (NESO)', 'Data may differ from actual data depending on the time accessed.': '数据可能会因访问时间的不同而有所不同。', 'Asset Status': '资产状态', 'Total NXPC Value': '总 NXPC 价值', 'No NXPC owned.': '没有拥有的 NXPC。', 'Bring with Swap&Warp': '携带 Swap&Warp', 'Total NESO Value': '总 NESO 价值', 'Setting': '设置', 'Profile': '简介', 'Nickname': '昵称', 'Change': '修改', 'Profile Image': '个人头像', 'Email Address': '电子邮件地址', 'Socials': '社交', 'Link': '链接', 'Service Restricted Location': '服务限制区域', 'MapleStory Universe is not yet available in your current location.': 'MapleStory 宇宙目前不可在您的当前位置使用。/n 请检查网络,加速器等', 'Confirm': '确认', 'Allow MSU Asset Access Permission': '允许 MSU 资产访问权限', 'Allowed': '允许', 'Delete Account': '删除账户', // https://msu.io/swapnwarp 'Swap': '兑换', 'Warp': '传送', 'Transactions': '交易', // https://static.msu.io/inspection 'Server Under Maintenance': '服务器维护中', 'We are currently undergoing scheduled maintenance to improve our services.We apologize for the inconvenience and appreciate your patience.Don\'t forget to keep up with our official channels for the latest updates.We hope to see you again soon!': '我们目前正在进行计划维护以改进我们的服务。\n对于造成的不便我们深表歉意,感谢您的耐心等待。\n请关注我们的官方渠道获取最新消息。\n期待很快与您再见!', 'MapleStory Universe is currently undergoing scheduled maintenance to improve our services.We apologize for the inconvenience and appreciate your patience.Don\'t forget to keep up with our official channels for the latest updates.We\'re excited to see you in MapleStory Universe: The Genesis soon!': '冒险岛N 目前正在进行计划维护以改进我们的服务。\n对于造成的不便我们深表歉意,感谢您的耐心等待。\n请关注我们的官方渠道获取最新消息。\n我们期待在《冒险岛宇宙:起源》中与您相见!', 'MapleStory Universe is not yet available in your location': '冒险岛N 目前不可在您的位置使用。\n请检查网络,加速器 \n并重启浏览器', 'We are working hard to expand our reach beyond the currently serviced regions. We thank you for your patience and your support.': '我们正在努力扩大我们的服务范围,以满足更多地区的需求。\n感谢您的耐心和支持。', }; /** * 创建悬浮控制按钮 */ // 自定义导航链接配置 const CUSTOM_NAV_LINK_URL = 'https://bbs.gjfmxd.com/'; // 自定义链接的URL const CUSTOM_NAV_LINK_TEXT = 'MSN工具箱'; // 自定义链接的文本 const CUSTOM_NAV_LINK_OPENS_NEW_TAB = true; // 是否在新标签页打开 const CUSTOM_NAV_LINK_HAS_ICON = true; // 是否显示外部链接图标 /** * 在导航栏中“新手上路”和“下载中心”之间添加自定义链接。 * 仅在 https://msu.io/maplestoryn/* 页面生效。 * @function addCustomLinkToNav */ /** * @function addCustomLinkToNav * @description Adds a custom navigation link to the MSU page header. * The link is inserted after the "游戏状态" (Game Status) link. */ function addCustomLinkToNav() { // 检查当前 URL 是否匹配 https://msu.io 主机并且路径以 /maplestoryn 开头 if (!(window.location.hostname === 'msu.io' && window.location.pathname.startsWith('/maplestoryn'))) { return; } // 防止重复添加 (checks for the LI element's ID) if (document.getElementById('custom-msu-nav-li')) { return; } // 查找“游戏状态”链接元素,作为插入自定义链接的参照点 const gameStatusLinkAnchor = document.querySelector('a[data-link="gnb-link"][href="/maplestoryn/gamestatus/ranking"]'); if (gameStatusLinkAnchor) { const gameStatusLi = gameStatusLinkAnchor.closest('li._componentlinkContainer__list_2gwfu_89'); if (gameStatusLi && gameStatusLi.parentElement) { // --- 自定义下拉菜单开始 --- const customLi = document.createElement('li'); customLi.id = 'custom-msu-nav-li'; customLi.className = '_componentlinkContainer__list_2gwfu_89'; // 匹配同级 li 的类名 const dropdownContainer = document.createElement('div'); dropdownContainer.className = '_dropdown_1nc4m_27'; // 下拉容器类名 // 主触发链接 (MSN工具箱) const triggerLink = document.createElement('a'); triggerLink.id = 'custom-msu-nav-link'; triggerLink.href = 'javascript:void(0);'; // 通常下拉触发器不直接导航 triggerLink.setAttribute('data-link', 'gnb-link'); triggerLink.setAttribute('aria-haspopup', 'listbox'); triggerLink.setAttribute('aria-expanded', 'false'); // 初始状态为折叠 triggerLink.textContent = '次元站'; // 下拉箭头图标 const triggerIcon = document.createElement('i'); triggerIcon.className = '_icon_keacv_5 _medium_keacv_24'; // 匹配游戏状态下拉图标类名 triggerIcon.style.transform = 'translateY(0px)'; triggerIcon.style.transition = '0.24s ease-out'; triggerIcon.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="M16.585 10.6508L12.7592 15.1142C12.3601 15.5798 11.6398 15.5798 11.2407 15.1142L7.41489 10.6508C6.85888 10.0021 7.31979 9 8.17415 9L15.8257 9C16.6801 9 17.141 10.0021 16.585 10.6508Z" fill="currentColor"></path></svg>'; triggerLink.appendChild(document.createTextNode(' ')); // 在文字和图标间加空格 triggerLink.appendChild(triggerIcon); // 下拉菜单本身 const dropdownMenu = document.createElement('div'); dropdownMenu.className = '_dropdown__default_pos_1nc4m_68 _dropdown__menu_1nc4m_81'; // 匹配游戏状态下拉菜单类名 dropdownMenu.setAttribute('role', 'listbox'); dropdownMenu.style.minWidth = '180px'; // 与游戏状态菜单宽度一致 dropdownMenu.style.display = 'none'; // 初始隐藏 // 下拉菜单顶部的三角指示器 // Create the SVG arrow using a string and insertAdjacentHTML for direct parsing by the browser. // This ensures the structure matches the user-provided working example as closely as possible. const svgArrowHTML = '<svg width="14" height="7" viewBox="0 0 14 7" fill="none" xmlns=" \`http://www.w3.org/2000/svg\` " class="_dropdown__tri_1nc4m_61"><path d="M7 0.814411L1.02232 8.5H12.9777L7 0.814411Z" fill="white" stroke="#121619"></path></svg>'; dropdownMenu.insertAdjacentHTML('afterbegin', svgArrowHTML); // 下拉菜单内部容器 const innerDropdown = document.createElement('div'); innerDropdown.className = '_inner_dropdown_1nc4m_126'; // 匹配游戏状态下拉菜单内部容器类名 // 根据子链接数量调整高度,每个约40px const subLinkHeight = 40; const numberOfSubLinks = 4; // 您将有3个子链接 innerDropdown.style.position = 'relative'; innerDropdown.style.height = (subLinkHeight * numberOfSubLinks) + 'px'; innerDropdown.style.width = '100%'; innerDropdown.style.overflow = 'auto'; // 如果内容超出则显示滚动条 const itemListDiv = document.createElement('div'); itemListDiv.style.height = (subLinkHeight * numberOfSubLinks) + 'px'; itemListDiv.style.width = '100%'; // 定义子链接 (用户可在此修改) // 每个对象包含: text (显示文本), url (链接地址), target (可选, e.g., '_blank' 在新标签页打开) const subLinks = [ { text: "职业介绍", url: "https://mxd.web.sdo.com/wiki/#/Classes", target: "_blank" }, { text: "BOSS介绍", url: "https://bbs.gjfmxd.com/thread-611.htm", target: "_blank" }, { text: "Link技能", url: "https://bbs.gjfmxd.com/thread-583.htm", target: "_blank" }, { text: "任务攻略(自行搜索)", url: "https://mxd.web.sdo.com/wiki/#/search", target: "_blank" } ]; subLinks.forEach((linkInfo, index) => { const subLink = document.createElement('a'); subLink.className = '_dropdown__item_1nc4m_104 _dropdown__list_1nc4m_101'; // 匹配游戏状态子链接类名 subLink.href = linkInfo.url; subLink.textContent = linkInfo.text; if (linkInfo.target) { subLink.target = linkInfo.target; } subLink.setAttribute('role', 'option'); subLink.style.position = 'absolute'; subLink.style.left = '0px'; subLink.style.top = (index * subLinkHeight) + 'px'; subLink.style.height = subLinkHeight + 'px'; subLink.style.width = '100%'; itemListDiv.appendChild(subLink); }); innerDropdown.appendChild(itemListDiv); dropdownMenu.appendChild(innerDropdown); // 组装结构 dropdownContainer.appendChild(triggerLink); dropdownContainer.appendChild(dropdownMenu); customLi.appendChild(dropdownContainer); // 事件处理:鼠标悬停显示/隐藏菜单 dropdownContainer.addEventListener('mouseenter', () => { dropdownMenu.style.display = 'block'; triggerLink.setAttribute('aria-expanded', 'true'); // 菜单打开时,箭头向上 triggerIcon.style.transform = 'translateY(-2px)'; const pathElement = triggerIcon.querySelector('svg path'); if (pathElement) { pathElement.setAttribute('d', 'M7.41504 13.3492L11.2408 8.8858C11.6399 8.42019 12.3602 8.42019 12.7593 8.8858L16.5851 13.3492C17.1411 13.9979 16.6802 15 15.8259 15H8.1743C7.31994 15 6.85903 13.9979 7.41504 13.3492Z'); // 向上箭头路径 } }); dropdownContainer.addEventListener('mouseleave', () => { dropdownMenu.style.display = 'none'; triggerLink.setAttribute('aria-expanded', 'false'); // 菜单关闭时,箭头向下并恢复位置 triggerIcon.style.transform = 'translateY(0px)'; const pathElement = triggerIcon.querySelector('svg path'); if (pathElement) { pathElement.setAttribute('d', 'M16.585 10.6508L12.7592 15.1142C12.3601 15.5798 11.6398 15.5798 11.2407 15.1142L7.41489 10.6508C6.85888 10.0021 7.31979 9 8.17415 9L15.8257 9C16.6801 9 17.141 10.0021 16.585 10.6508Z'); // 向下箭头路径 } }); // 将新的 <li> 插入到“游戏状态”链接的 <li> 之后 gameStatusLi.parentElement.insertBefore(customLi, gameStatusLi.nextSibling); // --- 自定义下拉菜单结束 --- } else { // console.warn('MSU Translation: "游戏状态" link\'s LI container not found or has no parent. Cannot add custom link.'); } } else { // console.warn('MSU Translation: "游戏状态" anchor link not found. Cannot add custom link.'); } } function createFloatingButton() { const button = document.createElement('button'); button.id = 'msu-translation-toggle'; button.className = 'msu-translation-button'; // 尝试从localStorage加载按钮位置 const savedBottom = localStorage.getItem('msu-button-bottom'); const savedRight = localStorage.getItem('msu-button-right'); // 按钮基础样式 button.style.position = 'fixed'; button.style.bottom = savedBottom || '30px'; // 使用保存的位置或默认值 button.style.right = savedRight || '30px'; // 使用保存的位置或默认值 button.style.zIndex = '10000'; button.style.width = '50px'; button.style.height = '50px'; button.style.borderRadius = '50%'; button.style.border = 'none'; button.style.cursor = 'grab'; // 初始光标为抓取 button.style.boxShadow = '0 4px 12px rgba(0,0,0,0.3)'; button.style.transition = 'transform 0.2s ease, background 0.3s ease'; button.style.display = 'block'; // 允许子元素绝对定位 button.style.backgroundImage = `url('https://globalstatic.xangle.io/explorer/nexon/logo/logo_mainnet_mobile.png')`; button.style.backgroundSize = 'contain'; button.style.backgroundRepeat = 'no-repeat'; button.style.backgroundPosition = 'center'; button.style.backgroundColor = 'transparent'; // 创建文本元素 const textSpan = document.createElement('span'); textSpan.id = 'msu-translation-text'; textSpan.textContent = isTranslationEnabled ? '汉' : '英'; // 设置初始文本 // 设置文本元素的样式,使其位于按钮右下角 textSpan.style.position = 'absolute'; textSpan.style.bottom = '-2px'; // 距离底部2px textSpan.style.right = '2px'; // 距离右侧2px textSpan.style.fontSize = '12px'; // 调整字体大小 textSpan.style.fontWeight = 'bold'; // 加粗字体 textSpan.style.color = '#000'; // 设置文字颜色为黑色 textSpan.style.backgroundColor = 'rgba(255, 255, 255, 0.3)'; // 添加半透明背景 textSpan.style.borderRadius = '3px'; // 圆角 textSpan.style.padding = '0 2px'; // 内边距 button.appendChild(textSpan); // 将文本添加到按钮中 if (!isTranslationEnabled) { button.style.filter = 'grayscale(100%)'; } // 拖动功能实现 let isDragging = false; let offsetX, offsetY; button.addEventListener('mousedown', (e) => { // 阻止点击事件的默认行为,防止与拖动冲突 // e.preventDefault(); isDragging = true; button.style.cursor = 'grabbing'; // 拖动时光标变为抓紧 // 计算鼠标点击位置相对于按钮左上角的偏移 offsetX = e.clientX - button.getBoundingClientRect().left; offsetY = e.clientY - button.getBoundingClientRect().top; // 移除可能的文本选择,提升拖动体验 window.getSelection().removeAllRanges(); }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; // 计算按钮新的 right 和 bottom 值 // window.innerWidth - e.clientX 是鼠标相对于窗口右边的距离 // button.offsetWidth - offsetX 是鼠标点击点相对于按钮右边的距离 // 新的 right = (鼠标相对于窗口右边的距离) - (鼠标点击点相对于按钮右边的距离) let newRight = window.innerWidth - e.clientX - (button.offsetWidth - offsetX); let newBottom = window.innerHeight - e.clientY - (button.offsetHeight - offsetY); // 边界检查,将按钮限制在右下角区域 const minRight = 0; // 按钮右边缘不能超出屏幕右边缘 const maxRightOverall = window.innerWidth - button.offsetWidth; // 按钮左边缘不能超出屏幕左边缘 const minBottom = 0; // 按钮下边缘不能超出屏幕下边缘 const maxBottomOverall = window.innerHeight - button.offsetHeight; // 按钮上边缘不能超出屏幕上边缘 // 右下角四分之一区域限制 // 应用X轴(左右)边界限制,限制在右侧四分之一区域 newRight = Math.max(0, Math.min(newRight, (window.innerWidth * 0.25) - button.offsetWidth)); // 应用Y轴(上下)边界限制,限制在底部四分之一区域 newBottom = Math.max(0, Math.min(newBottom, (window.innerHeight * 0.25) - button.offsetHeight)); button.style.right = `${newRight}px`; button.style.bottom = `${newBottom}px`; }); document.addEventListener('mouseup', () => { if (isDragging) { isDragging = false; button.style.cursor = 'grab'; // 拖动结束,光标恢复 // 保存按钮位置到localStorage localStorage.setItem('msu-button-bottom', button.style.bottom); localStorage.setItem('msu-button-right', button.style.right); } }); // 鼠标悬停效果 (在拖动逻辑之后,避免冲突) button.addEventListener('mouseenter', () => { if (!isDragging) { // 仅在非拖动状态下应用悬停效果 button.style.transform = 'scale(1.1)'; button.style.opacity = '0.9'; } }); button.addEventListener('mouseleave', () => { if (!isDragging) { button.style.transform = 'scale(1)'; button.style.opacity = '1'; } }); // 点击事件 (需要处理与拖动的区分) let clickTimestamp = 0; button.addEventListener('mousedown', () => { clickTimestamp = Date.now(); // 记录按下时间 }); button.addEventListener('click', (e) => { // 如果 mousedown 和 click 事件之间的时间差很小,且没有发生拖动,则视为点击 // isDragging 状态会在 mouseup 时重置,所以这里用时间差辅助判断 if (Date.now() - clickTimestamp < 200 ) { // 200ms 内视为点击 isTranslationEnabled = !isTranslationEnabled; if (isTranslationEnabled) { button.style.filter = 'none'; } else { button.style.filter = 'grayscale(100%)'; } saveTranslationState(isTranslationEnabled); // 更新按钮文本 const textSpan = document.getElementById('msu-translation-text'); if (textSpan) { textSpan.textContent = isTranslationEnabled ? '汉' : '英'; } if (isTranslationEnabled) { translateElement(document.body); } else { location.reload(); } } }); document.body.appendChild(button); } /** * 遍历元素并应用翻译 * @param {Element} element - 要处理的DOM元素 */ function translateElement(element) { // 如果翻译已禁用则跳过 if (!isTranslationEnabled) return; // 跳过脚本, 样式等非文本元素 if (element.tagName === 'SCRIPT' || element.tagName === 'STYLE') return; // 处理文本节点 if (element.nodeType === Node.TEXT_NODE) { const originalText = element.textContent.trim(); // 查找不区分大小写的匹配项,支持复数形式 // 处理带日期的特殊文本 if (originalText.startsWith('Sale ends on ')) { const datePart = originalText.substring('Sale ends on '.length); if (/\d{4}-\d{2}-\d{2} \d{2}:\d{2}/.test(datePart)) { element.textContent = '销售截止于 ' + datePart; return; } } // 新增:处理 “There is a new highest offer for [物品名称].” const offerMatch = originalText.match(/^There is a new highest offer for (.*)\.$/i); if (offerMatch) { const itemName = offerMatch[1].trim(); const translatedItemName = CUSTOM_DICT[itemName] || itemName; element.textContent = `${translatedItemName} 有一个新的最高报价。`; return; } // 新增:处理时间格式文本,例如 "X sec ago", "X min ago", "X hours ago", "X day ago", "X days ago" const timeAgoMatch = originalText.match(/^(\d+)\s+(sec|secs|min|mins|hour|hours|day|days)\s+ago$/i); if (timeAgoMatch) { const value = parseInt(timeAgoMatch[1], 10); const unit = timeAgoMatch[2].toLowerCase(); let translatedText = ''; if (unit === 'min' || unit === 'mins') { translatedText = `${value} 分钟前`; } else if (unit === 'hour' || unit === 'hours') { translatedText = `${value} 小时前`; } else if (unit === 'day' || unit === 'days') { translatedText = `${value} 天前`; } else if (unit === 'sec' || unit === 'secs') { translatedText = `${value} 秒前`; } if (translatedText) { element.textContent = translatedText; return; // 已处理,提前返回 } } // 新增:处理宠物技能组合翻译 // 检查文本是否包含逗号,并且第一个技能是 'Item Pouch' (宠物技能组合通常以此开头) if (originalText.includes(',') && originalText.startsWith('Item Pouch')) { const skills = originalText.split(',').map(skill => skill.trim()); const translatedSkills = skills.map(skill => { // 查找单个技能的翻译 const matchedSkillKey = Object.keys(CUSTOM_DICT).find( key => key.toLowerCase().replace(/[’']/g, "'") === skill.toLowerCase().replace(/[’']/g, "'") ); return matchedSkillKey ? CUSTOM_DICT[matchedSkillKey] : skill; // 如果找到翻译则使用,否则保留原文本 }); // 重新组合翻译后的技能名称并添加数量 element.textContent = translatedSkills.join(', ') + ` (${translatedSkills.length})`; return; // 已处理,提前返回 } // 特殊处理'Top'与'Traders'同时出现的情况 if (originalText === 'Top' && element.parentElement && Array.from(element.parentElement.children).some(child => child.textContent.includes('Traders') )) { element.textContent = 'Top榜'; return; } // 新增:特殊处理 'Record-' 和 'breaking' 的组合 // 例如:<span>Record-</span><br><span>breaking</span> if (originalText === 'Record-' && element.parentNode && element.parentNode.tagName === 'SPAN') { let currentSibling = element.parentNode.nextSibling; let breakingSpan = null; // 遍历兄弟节点,寻找 'breaking' 所在的 SPAN,可以跳过 BR 标签 while (currentSibling) { if (currentSibling.nodeType === Node.ELEMENT_NODE) { // 只处理元素节点 if (currentSibling.tagName === 'SPAN' && currentSibling.textContent.trim().toLowerCase() === 'breaking') { breakingSpan = currentSibling; break; // 找到了目标 SPAN } else if (currentSibling.tagName !== 'BR') { // 如果遇到非 BR 的其他元素,则停止搜索,说明结构不匹配 break; } } currentSibling = currentSibling.nextSibling; } if (breakingSpan) { element.textContent = ''; // 清空 "Record-" 所在的文本节点 breakingSpan.textContent = '历史新高'; // 翻译 "breaking" SPAN 的内容 return; // 已处理此特殊组合,提前返回 } } // 如果不是数字,再尝试匹配字典 const matchedKey = Object.keys(CUSTOM_DICT).find( key => { // 标准化键名和文本,处理特殊字符 const normalizedKey = key.toLowerCase().replace(/[’']/g, "'"); const normalizedText = originalText.toLowerCase().replace(/[’']/g, "'"); const keyWithoutSpaces = normalizedKey.replace(/\s+/g, ''); const textWithoutSpaces = normalizedText.replace(/\s+/g, ''); // 完全匹配或复数形式匹配(以s结尾)或无空格匹配 return normalizedKey === normalizedText || (normalizedText.endsWith('s') && normalizedKey === normalizedText.slice(0, -1)) || keyWithoutSpaces === textWithoutSpaces; } ); if (matchedKey) { element.textContent = element.textContent.replace(originalText, CUSTOM_DICT[matchedKey]); } } // 递归处理子元素 for (const child of element.childNodes) { translateElement(child); } } // 页面加载完成后触发翻译 window.addEventListener('load', () => { createFloatingButton(); addCustomLinkToNav(); // 添加自定义导航链接 if (isTranslationEnabled) { translateElement(document.body); } // 监听DOM变化(处理动态加载内容和按钮移除) const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // 检查移除的节点 mutation.removedNodes.forEach((node) => { if (node.id === 'msu-translation-toggle') { createFloatingButton(); addCustomLinkToNav(); // 添加自定义导航链接 } }); // 处理新增节点和文本变化 mutation.addedNodes.forEach((node) => { if (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE) { translateElement(node); } }); // 处理属性变化 if (mutation.type === 'attributes') { translateElement(mutation.target); } }); }); // 监听整个文档的交互事件 document.addEventListener('click', (event) => { // 延迟执行以确保DOM更新完成 setTimeout(() => { if (isTranslationEnabled) { translateElement(document.body); } }, 100); }); observer.observe(document.body, { childList: true, subtree: true, characterData: true, characterDataOldValue: true, attributes: true, attributeOldValue: true }); }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址