您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
优先显示原文(title->value),以及中文化(mainMap[value]->value)
当前为
// ==UserScript== // @name VNDB优先原文和中文化 // @namespace http://tampermonkey.net/ // @version 4.2.1 // @description 优先显示原文(title->value),以及中文化(mainMap[value]->value) // @author aotmd // @match https://vndb.org/* // @noframes // @license MIT // @run-at document-body // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // ==/UserScript== /**-------------------------------数据部分[850行]-------------------------------------*/ /*通用主map,作用在全局*/ let mainMap = { /**左侧栏[常驻]*/ /*菜单*/ "Support VNDB": "赞助 VNDB", "Patreon": "Patreon", "SubscribeStar": "SubscribeStar", "Menu": "菜单", "Home": "首页", "Visual novels": "视觉小说", "Tags": "标签", "Releases": "版本", "Producers": "制作人", "Staff": "工作人员", "Characters": "人物", "Traits": "特征", "Users": "用户", "Recent changes": "最近更改", "Discussion board": "讨论区", "FAQ": "常见问题", "Random visual novel": "随机视觉小说", "Dumps": "转储", "API": "API", "Query": "查询", "Search": "搜索", "search": "搜索", /*我的*/ "My Profile": "我的个人资料", "My Visual Novel List": "我的视觉小说列表", "My Votes": "我的评分", "My Wishlist": "我的愿望单", "My Notifications": "我的通知", "My Recent Changes": "我的最近更改", "My Tags": "我的标签", "Image Flagging": "图片标记", "Add Visual Novel": "添加视觉小说", "Add Producer": "添加制作人", "Add Staff": "添加工作人员", "Logout": "退出登录(不可用)", /*未登陆状态*/ "User menu": "用户菜单", "Login": "登录(不可用)", "Password reset": "重置密码", "Register": "注册(不可用)", /*数据库统计*/ "Database Statistics": "数据库统计", "Visual Novels": "视觉小说", /** 标题和,底部[常驻] */ "the visual novel database": "视觉小说数据库", "about us": "关于我们", /** 额外map提升*/ /*个人页相关*/ "Arabic": "阿拉伯语", "Bulgarian": "保加利亚语", "Catalan": "加泰罗尼亚语", "Chinese": "中文", "Chinese (simplified)": "中文(简体)", "Chinese (traditional)": "中文(繁体)", "Croatian": "克罗地亚语", "Czech": "捷克语", "Danish": "丹麦语", "Dutch": "荷兰语", "English": "英语", "Esperanto": "世界语", "Finnish": "芬兰语", "French": "法语", "German": "德语", "Greek": "希腊语", "Hebrew": "希伯来语", "Hindi": "印地语", "Hungarian": "匈牙利语", "Indonesian": "印尼语", "Irish": "爱尔兰语", "Italian": "意大利语", "Japanese": "日语", "Korean": "韩语", "Latin": "拉丁语", "Latvian": "拉脱维亚语", "Lithuanian": "立陶宛语", "Macedonian": "马其顿语", "Malay": "马来语", "Norwegian": "挪威语", "Persian": "波斯语", "Polish": "波兰语", "Portuguese (Brazil)": "葡萄牙语(巴西)", "Portuguese (Portugal)": "葡萄牙语(葡萄牙)", "Romanian": "罗马尼亚语", "Russian": "俄语", "Scottish Gaelic": "苏格兰盖尔语", "Slovak": "斯洛伐克语", "Slovene": "斯洛文尼亚语", "Spanish": "西班牙语", "Swedish": "瑞典语", "Tagalog": "塔加洛语", "Thai": "泰语", "Turkish": "土耳其语", "Ukrainian": "乌克兰语", "Urdu": "乌尔都语", "Vietnamese": "越南语", /*评分说明*/ "masterpiece": "杰作|超神作", "excellent": "极好|神作", "so-so": "一般般|不过不失", "very good": "很好|力荐", "good": "好|推荐", "decent": "不错|还行", "weak": "不太行|较差", "bad": "糟糕|差", "awful": "很坏|很差", "worst ever": "最差|不忍直视", "Vote stats": "评分统计", "Recent votes": "最近评分", "show all": "显示全部", "Report an issue on this page.": "在此页面上报告问题。", }; /** * 用以替换title的值,若mainMap有则会自动替换,不需要再重复在这写一遍 * @type {{Object}} */ let titleMap={ }; /** 特殊全局map,用以替换变动的文本节点[正则], * value出现的%%$1%%为需要继续翻译值 * vlaue出现的%%@@$1@@%%将$1转小写,然后继续翻译值 * */ let specialMap = { /*转小写再匹配map,范围太广不使用*/ // "^([a-zA-Z -]+)$":"%%@@$1@@%%", /** 游戏详情页,评分统计 /v\d+ */ "^(\\d+) vote[s]? total, average ([\\d.]+) \\(([a-zA-Z -]+)\\)$": "总共$1票, 平均分$2 (%%$3%%)", /** 讨论 */ "^discussions \\((\\d+)\\)$": "讨论 ($1)", }; /*额外map,作用在指定页面*/ let otherPageRules = [ { /*作用页说明*/ name: '个人页相关', /*正则表达式*/ regular: /\/u\d+/i, /*mainMap k->v*/ map: { /** 用户页顶栏 /ID */ "edit": "编辑", "list": "列表", "votes": "评分", "wishlist": "愿望单", "reviews": "评论", "posts": "帖子", "history": "历史", /** 个人资料页 /ID */ "Username": "用户名", "Registered": "注册(不可用)日期", "Edits": "编辑", "Votes": "评分", "Browse votes »": "浏览评分 »", "Play times": "游戏时间", "List stats": "列表统计", "Browse list »": "浏览列表 »", "Reviews": "评论", "Browse reviews »": "浏览评论 »", "Browse tags »":"浏览标签 »", "Images": "图片", "Browse image votes »": "浏览图片投票 »", "Forum stats": "论坛统计", "Browse posts »": "浏览帖子 »", "Vote statistics": "评分统计", // "Vote stats": "评分统计", // "Recent votes": "最近评分", // "show all": "显示全部", /** 编辑页 /ID/edit */ "My Account": "我的账号", "Account settings": "账号设置", "change": "修改", "E-Mail": "电子邮箱", "Change password": "更改密码", "Preferences": "偏好", "NSFW": "NSFW", "Hide sexually suggestive or explicit images": "隐藏性暗示或色情图片", "Hide all images": "隐藏所有图片", "Hide only sexually explicit images": "只隐藏色情图片", "Don't hide suggestive or explicit images": "不隐藏性暗示或色情图片", "Hide violent or brutal images": "隐藏暴力或残暴图片", "Hide only brutal images": "只隐藏残暴的图片", "Don't hide violent or brutal images": "不隐藏暴力或残暴的图片", "Show sexual traits by default on character pages": "默认情况下在人物页面上显示性特征", "Title language": "标题语言", "Add language": "添加语言", "Original language": "原始语言", "romanized": "罗马化", "Alternative title": "副标题", "The alternative title is displayed below the main title and as tooltip for links.": "副标题显示在主标题下方,并作为链接的提示", /*语言相关已提升至主map*/ "remove": "移除", "Show all tags by default on visual novel pages (don't summarize)": "在视觉小说页面上默认显示所有标签(不汇总)", "Default tag categories on visual novel pages:": "视觉小说页面上默认显示的标签类别:", "Content": "内容", "Sexual content": "色情内容", "Technical": "技术相关", "Spoiler level": "剧透级别", "Hide spoilers": "隐藏剧透", "Show only minor spoilers": "仅显示轻微剧透", "Show all spoilers": "显示所有剧透", "Skin": "皮肤", "AIR (sky blue)": "AIR(天蓝)", "Angelic Serenade (dark blue)": "エンジェリックセレナーデ 天使小夜曲(深蓝色)", "EIeL (peach-orange)": "電脳妖精エルファン (桃橙色)", "Eien no Aselia (falu red)": "永遠のアセリア 永远的艾塞莉娅 (法鲁红)", "Ever17 (bondi blue)": "ever17 (邦迪蓝)", "Fate/stay night (pale carmine)": "fate/stay night (淡胭脂红)", "Fate/stay night (seal brown)": "fate/stay night (海豹棕)", "Gekkou no Carnevale (black)": "月光のカルネヴァーレ 月光嘉年华(黑色)", "Higanbana no Saku Yoru ni (maroon)": "彼岸花の咲く夜に 彼岸花盛开之夜 (栗色)", "Higurashi no Naku Koro ni (orange)": "ひぐらしのなく頃に 寒蝉鸣泣之时 (橙色)", "Little Busters! (lemon chiffon)": "リトルバスターズ! little busters! (柠檬雪纺)", "Little Busters! (pink)": "リトルバスターズ! little busters! (粉色)", "Neon (black)": "荧光 (黑色)", "Primitive Link (pale chestnut)": "プリミティブ リンク primitive link (淡栗子)", "Saya no Uta (dark scarlet)": "沙耶の唄 沙耶之歌 (深红)", "Seinarukana (white)": "聖なるかな -The Spirit of Eternity Sword 2- (白色)", "Sora no Iro, Mizu no Iro (turquoise)": "そらのいろ、みずのいろ 空之色,水之色 (绿松石)", "Teal (teal)": "青色 (青色)", "Touhou (grey)": "东方 (灰色)", "Tsukihime (black)": "月姫 (黑色)", "Tsukihime (midnight blue)": "月姫 (午夜蓝)", "Custom CSS": "自定义CSS", "Public profile": "公开资料", "You can add": "您可以添加", "character traits": "性格特征", "to your account. These will be displayed on your public profile.": "到您的帐户。这些资料会公开显示。", "No results": "无结果", "Add trait...": "添加特征...", "Submit": "提交", /*在选择后出现的新文本:*/ "Only if original title": "仅当是原始标题时", "Only if official title": "仅当是官方标题时", "Include non-official titles": "也包括非官方标题", "New username": "新用户名", "You may only change your username once a day. Your old username(s) will be displayed on your profile for a month after the change.": "您每天只能更改一次用户名。更改用户名后,旧用户名会在个人资料中显示一个月。", "Old password": "旧密码", "New password": "新密码", "Repeat": "重复新密码", /** 列表页 /ID/ulist?vnlist=1 */ "My list": "我的列表", "ALL": "显示全部", "Voted": "已评分", "No label": "无标签", "Multi-select": "多选", "Update filters": "更新过滤器", /*标签管理*/ "Manage labels": "标签管理", "How to use labels": "如何使用标签", "You can assign multiple labels to a visual novel": "您可以为视觉小说分配多个标签", "You can create custom labels or just use the built-in labels": "您可以创建自定义标签或仅使用内置标签", "Private labels will not be visible to other users": "其他用户看不见私有标签", "Your vote and notes will be public when at least one non-private label has been assigned to the visual novel": "当视觉小说分配了至少一个非私有标签时,您的评分和笔记将是公开状态", "VNs": "VN数量", "Label": "标签", "Private": "私有性", "New label": "新建标签 ", "Save changes": "保存更改", "private": "私有", "built-in": "内置的", "applied when you vote": "当你评分时更新", /*保存为默认值*/ "Save as default": "保存为默认值", "This will change the default label selection, visible columns and table sorting options for the selected page to the currently applied settings.": "这将把所选页面的默认标签选择、可见列和排序方式更改为当前的设置。", "The saved view will also apply to users visiting your lists.": "保存的视图也会应用于访问您列表的用户。", "(If you just changed the label filters, make sure to hit \"Update filters\" before saving)": "(如果您刚刚更改了标签过滤器,请在保存默认设置之前点击\"更新过滤器\")", "Save": "保存", /*导出*/ "Export": "导出", "Export your list": "导出您的列表", "This function will export all visual novels and releases in your list, even those marked as private (there is currently no import function, more export options may be added later).": "此功能将导出您列表中的所有视觉小说和发行版本,包括标签为私有的(目前没有导入功能,以后可能会添加更多导出选项)", "Download XML export.": "下载XML导出.", /*显示选项*/ "display options": "显示选项", "Order by": "排序方式", "Results": "显示数量", "Update": "更新", "Visible": "可见", "columns": "列", /*排序标记*/ "Title": "标题", "Vote date": "评分时间", "Vote": "评分", "Rating": "评价", "Labels": "标签", "Added": "添加时间", "Modified": "修改时间", "Start date": "开始日期", "Finish date": "完成日期", "Release date": "发布日期", /*标签状态*/ "Playing": "在玩", "Finished": "玩过", "Stalled": "搁置", "Dropped": "抛弃", "Wishlist": "愿望单", "Blacklist": "黑名单", /*Opt*/ "Opt": "选择", 'Notes': '笔记', 'Remove VN': '删除 VN', '-- add release --': '--添加版本--', 'Add release': '添加版本', /*版本,状态*/ "Obtained": "已得到", "Unknown": "未知", "Pending": "待定", "On loan": "外借", "Deleted": "已删除", /*翻页按钮*/ "next ›": "下一页 ›", "last »": "尾页 »", "« first":"« 首页", "‹ previous":"‹ 上一页", /*其他动态信息*/ "Loading releases...":"正在加载版本...", "Keep label": "保留标签", "Delete label but keep VNs in my list": "删除标签,但保留VN在我的列表中", "Delete label and VNs with only this label": "删除标签,也删除只有这个标签的所有VN", "Delete label and all VNs with this label": "删除标签,也删除带有这个标签的所有VN", "WARNING: ":"警告: ", "Your vote is still public if you assign a non-private label to the visual novel.":"如果你给视觉小说指定了非私有标签,你的评分仍然是公开的。", /** 评论*/ "You have not submitted any reviews yet.": "您还没有提交任何评论。", /** 帖子*/ "My posts": "我的帖子", "You have not posted anything on the forums yet.": "您还没有在论坛上发布任何内容。", /** 历史*/ "Docs": "文档", "All": "全部", "Only changes to existing items": "仅更改的项目", "Only newly created items": "仅新创建的项目", "Only public items": "仅限公共项目", "Only deleted": "仅删除", "Only unapproved": "仅未批准", "Rev.": "修订版.", "Date": "日期", "User": "用户", "Page": "页面", /** 我的通知 /notifies*/ "My notifications": "我的通知", "Unread notifications": "未读通知", "All notifications": "所有通知", "No notifications!": "没有通知!", "Settings": "设置", "Notify me about edits of database entries I contributed to.": "通知关于我参与的数据库条目的编辑。", "Notify me about replies to threads I posted in.": "通知关于我发布的主题的回复。", "Notify me about comments to my reviews.": "通知关于我的评论的评论。", "Notify me about site announcements.": "通知有关站点公告的信息。", }, titleMap:{ "This item is public": "此项是公开的", }, specialMap: { /** 个人资料页 /ID */ "^(.+)'s profile$": "$1 的个人资料", "^(\\d+)h$": "$1小时", "^(\\d+)m$": "$1分钟", "^from (\\d+) submitted play times.$": ",来自$1个游戏.", "^(\\d+) release[s]? of (\\d+) visual novels.$": "$1个版本,$2部视觉小说.", "^(\\d+) review[s]?.":"$1个评论.", "^(\\d+) vote[s]? on (\\d+) distinct tag[s]? and (\\d+) visual novel[s]?.":"在$2个不同标签和$3部视觉小说上投了$1票。", "^(\\d+) images flagged.$": "标记了$1个图片.", "^(\\d+) post[s]?, (\\d+) new thread[s]?.": "$1个帖子, $2个新主题.", /*评分统计*/ "^(\\d+) votes, ([\\d.]+) average.$": "$1个评分, 平均$2分.", "^(\\d+) votes total, average ([\\d.]+)$": "$1个评分, 平均$2分", /*他人主页*/ "^(\\d+)h from (\\d+) submitted play times.$": "$1小时,来自$1个游戏.", /** 列表页 /ID/ulist?vnlist=1 */ /*排序头*/ "^([a-zA-Z ]+) ▴$":"%%$1%% ▴", /*评分说明(下拉列表,选择分数时)*/ "^(\\d+) \\(([a-zA-Z -]+)\\)$": "$1 (%%$2%%)", /** 评论*/ "^Reviews by (.+)$": "$1的评论", /** 历史*/ "^Edit history of (.+)$": "$1的编辑历史", }, }, { name: '登录(不可用)|注册(不可用)|重置密码', regular: /\/u\/(login|newpass|register)/i, map: { /*登陆页*/ "Username": "用户名", "No account yet?": "还没有账号?", "Password": "密码", "Forgot your password?": "忘记密码?", "Submit": "提交", /*重置密码*/ "E-Mail": "电子邮箱", "Forgot Password": "忘记密码", "Forgot your password and can't login to VNDB anymore?": "忘记密码,登录(不可用)不了VNDB?", "Don't worry! Just give us the email address you used to register on VNDB": "别担心!只需提供您在VNDB上注册(不可用)时的电子邮箱地址", "and we'll send you instructions to set a new password within a few minutes!": "我们将在几分钟内向您发送设置新密码的说明!", /*注册(不可用)账号*/ "Create an account": "创建账号", "Preferred username. Must be between 2 and 15 characters long and consist entirely of alphanumeric characters or a dash.": "首选用户名。长度必须在2到15个字符之间,由字母数字或-组成。", "Names that look like database identifiers (i.e. a single letter followed by several numbers) are also disallowed.": "看起来像数据库标识符的名称(即一个字母后跟几个数字)也不允许使用。", "A valid address is required in order to activate and use your account.": "需要有效地址才能激活和使用您的帐户。", "Other than that, your address is only used in case you lose your password,": "除此之外,您的地址仅在您丢失密码的情况下使用,", "we will never send spam or newsletters unless you explicitly ask us for it or we get hacked.": "我们永远不会发送垃圾信息或时事通讯,除非您明确要求我们这样做,要不就是我们被黑客攻击了。", "Anti-bot question: How many visual novels do we have in the database? (Hint: look to your left)": "反机器人问题:数据库中有多少视觉小说?(提示:向左看)", "Answer": "回答", }, titleMap:{ }, specialMap: { }, }, { name:'首页右侧主板', regular:/^\/$/i, map:{ "The Visual Novel Database": "视觉小说数据库", "VNDB.org strives to be a comprehensive database for information about visual novels.": "VNDB.org致力于成为一个全面的视觉小说信息数据库。", "This website is built as a wiki, meaning that anyone can freely add\n and contribute information to the database, allowing us to create the\n largest, most accurate and most up-to-date visual novel database on the web.": "这个网站是作为一个维基建立的,这意味着任何人都可以自由地向数据库添加和贡献信息,这让我们能够创建网络上最大、最准确和最新的视觉小说数据库。", "Recent Changes": "最近更改", "Announcements": "公告", "VNDB": "VNDB", "DB Discussions": "数据库讨论", "Forums": "论坛", "VN Discussions": "VN讨论", "Latest Reviews": "最新评论", "Upcoming Releases": "即将发布的版本", "Just Released": "刚刚发布的版本", }, titleMap:{ }, specialMap:{ }, }, { name:'讨论板|讨论区', regular:/^\/t\/.+/i, map:{ /** 自己的讨论*/ "Index": "主页", "All boards": "全部板块", "VNDB discussions": "VNDB 讨论", "General discussions": "一般讨论", "Start a new thread": "创建一个新帖子", "An empty board": "空的板块", "Nobody's started a discussion on this board yet. Why not": "还没有人在这块板上开始讨论。为什么不", "create a new thread": "创建一个新帖子", "yourself?": ",由你自己?", /** 全部讨论*/ "Search!": "搜索!", "Topic": "主题", "Replies": "回复", "Starter": "发表人", "Last post": "最近回复", "Discussion board index":"讨论区主页", /* 主题标题标签*/ "[poll]":"[投票]", /** 创建一个新帖子*/ "Create new thread": "创建新帖子", "Thread title": "帖子标题", "Boards": "板块", "You can link this thread to multiple boards. Every visual novel, producer and user in the database has its own board,": "你可以将这个帖子链接到多个版块。数据库中的每个视觉小说、制片人和用户都有自己的版块,", "but you can also use the \"General Discussions\" and \"VNDB Discussions\" boards for threads that do not fit at a particular database entry.": "但您也可以使用\"一般讨论\"或\"VNDB讨论\"板来处理不适合特定数据库条目的帖子。", "Add boards...": "添加板块...", "Message": "信息", "(English please!)": "(请用英语!)", "Formatting": "可用的格式代码", "Edit": "编辑", "Preview": "预览", "Add poll": "添加投票", /*一些表单提示信息*/ "Please add at least one board.": "请添加至少一个板块。", "The form contains errors, please fix these before submitting.": "表单包含错误,请在提交前修复这些错误。", "List contains duplicates.":"列表包含重复项", /*投票*/ "Poll question": "投票问题", "Options": "选项", "Add option": "添加选项", "Number of options people are allowed to choose.": "允许用户选择的选项数量。", /* 查看其他人的帖子*/ "Posted in": "发表于", "report": "举报", "Quick reply": "快速回复", }, titleMap:{ }, specialMap:{ /** 自己的讨论*/ "^Related discussions for (.+)$": "$1的相关讨论", /** 创建一个新帖子*/ /*投票*/ "^Option #(\\d+)$": "选项 #$1", }, }, { name:'我的标签|标签', regular:/^\/g\/links/i, map:{ /*我的标签*/ "Tag link browser": "标签链接浏览器", "Active filters:": "活动过滤器:", "] User:": "] 用户:", "No tag votes matching the requested filters.": "没有与要求的过滤器匹配的标签评分。", /*表头*/ "Click the arrow before a user, tag or VN to add it as a filter.": "单击用户、标签或视觉小说之前的箭头,可以将其添加为筛选器。", "Tag": "标签", "Spoiler": "剧透", "Visual novel": "视觉小说", "Note": "笔记", /*剧透级别*/ "minor spoiler": "轻微剧透", "no spoiler": "没有剧透", "major spoiler": "严重剧透", }, titleMap:{}, specialMap:{}, }, { name:'举报页面', regular:/^\/report/i, map:{ "Submit report": "提交举报", "Subject": "主题", "Comment": "评论", "Your report will be forwarded to a moderator.": "您的举报将转发给版主。", "Keep in mind that not every report will be acted upon, we may decide that the problem you reported is still within acceptable limits.": "请记住,并非每个举报都会被处理,我们可能会认为您举报的问题仍在可接受的范围内。", "We generally do not provide feedback on reports, but a moderator may decide to contact you for clarification.": "我们通常不会对举报提供反馈,但版主可能会决定与您联系以进行解释。", "Reason": "理由", "-- Select --": "-- 选择 --", "Spam": "垃圾邮件", "Links to piracy or illegal content": "盗版或非法内容链接", "Off-topic": "与主题无关", "Unwelcome behavior": "不受欢迎的行为", "Unmarked spoilers": "没有标记剧透", "Other": "其他", }, titleMap:{}, specialMap:{}, }, { name:'特征页|标签页|作品详情页|用户主页', regular:/^\/(i|g|v\d+$|u\d+$)/i, map:{ /*大类*/ "Hair":"毛发", "Eyes":"眼睛", "Body":"身体", "Clothes":"服装", "Items":"物品", "Personality":"性格", "Role":"角色", "Engages in (Sexual)":"主动(性)", "Subject of (Sexual)":"被动(性)", "Engages in":"主动", "Subject of":"被动", /*细分*/ "Sexual Content":"色情内容", // "ADV":"ADV", "Male Protagonist":"男性主角", "Penetrative Sex":"插入式做爱", "No Sexual Content":"无色情内容", "Student":"学生", "Multiple Endings":"多分支结局", "High Sexual Content":"大量的性爱场景", "Fantasy":"奇幻", "Romance":"恋爱", "Female Protagonist":"女性主角", "Drama":"戏剧", "Nukige":"拔作", "Non-penetrative Sex":"非插入式做爱", "Protagonist with a Face":"主角露过正脸", "Blowjob":"阴茎口交", "Group Sex":"群交", "Student Heroine":"女主角是学生", "Darker Sexual Contents":"更黑暗的色情内容", "Sexual Harassment":"性骚扰", "Defloration":"破处场景", "Rape":"强奸", "School":"学校", "Other Gameplay Elements":"其他游戏类可玩性", "High School Student":"高中生", "Fictional Beings":"虚构物种", "Doggy Style":"狗交式体位", // "BDSM":"BDSM", "Earth":"游戏背景地球", "Cowgirl":"女上位体位", "Big Breast Sizes Heroine":"大胸女主角", "Sexual Devices":"性玩具", "High School Student Heroine":"高中生女主角", "Customization":"捏人或自定义物品", "Comedy":"喜剧", "Bad Ending(s)":"坏结局", "Modern Day":"游戏背景现代", "Anal Penetration":"肛门插入", "Student Protagonist":"学生主角", "Group Sex of One Male and Several Females":"一男多女群交", "Linear Plot":"无分支/选项无影响", "Nameable Character(s)":"角色可命名", "Nameable Protagonist":"主角可命名", "Incest":"乱伦", "Boobjob":"乳交", "Missionary Position":"男上位体位", "Otome Game":"乙女类游戏", "Health Issues":"角色身体健康问题", "Cunnilingus":"舔穴", "Mystery":"悬疑", "Single Blowjob":"单人阴茎口交", "Non-human Heroine":"非人类女主角", "Single Ending":"单结局", "Outdoor Sex":"户外做爱", "Changing Perspective":"视角切换", "Modern Day Earth":"游戏背景现代地球", "Psychological Problems":"角色心理健康问题", "Handjob":"阴茎手交", "Organizations":"组织", "Bondage":"捆绑", "Heroine with Big Breasts":"大胸女主角", "Masturbation":"自慰", "Sex in Public Places":"公共场所做爱", "Group Sex of One Female and Several Males":"一女多男群交", "Fingering":"指交", "Crime":"犯罪情节", "Science Fiction":"科幻", "Voice Acting":"配音", "Lesbian Sex":"女性之间做爱", "Standing Sex":"站立式体位", "Naked Sprites":"裸体立绘", "Sitting Sex":"坐姿做爱", "Only a Single Heroine":"单女主角", "Adult Heroine":"成人女主角", "Loli Heroine":"萝莉女主角", "Sixty-nine":"69式体位", "Branching Plot":"分支剧情", "Monsters":"怪物", "Relationship Problems":"感情危机", "Adult Protagonist":"成人主角", "Kinetic Novel":"视觉小说(无选项)", "Multiple Penetration":"多重插入", "Vibrators":"振动棒", "Event CGs":"事件CG", "Pregnancy":"怀孕", "Protagonist's Sister as a Heroine":"主角的姐姐或妹妹为女主角", "Anal Sex":"肛交", "Heroine with Glasses":"眼镜娘女主角", "Quickie Fix Position":"站立后入", "Fighting Heroine":"有武力的女主角", "Mythical Setting":"取材自神话传说", "Only Virgin Heroines":"全处女主角", "Harem Ending":"后宫结局", "Brother/Sister Incest":"兄弟姐妹间做爱", "Protagonist's Childhood Friend as a Heroine":"幼驯染女主角", "Other Perspectives":"其他人视角", "Blood-related Incest":"近亲乱伦", "Modern Day Japan":"游戏背景现代日本", "Sex with Protagonist Only":"仅主角有性爱场景", "Side Portraits":"文本框旁副立绘", "Divine Beings":"神话生物", "Bukkake":"精液沐浴", "Violence":"暴力", "Twin Tail Heroine":"双马尾女主角", "Pregnant Sex":"孕交", "Immortal Heroine":"永生的女主角", "Jealousy":"嫉妒感情", "High School":"高中", "Tsundere Heroine":"傲娇女主角", "Protagonist with a Sprite":"主角有立绘", "High School Student Protagonist":"高中生主角", "Action":"动作元素", "Sex With Monsters":"与虚构生物做爱场景", "Single Boobjob":"单人乳交", "Bathroom Sex":"浴室做爱", "Urination Fetish":"排尿性爱", "Early Sexual Content":"游戏前期出现性内容", "Footjob":"足交", "Heroine with Sexual Experience":"有过性经验的女主角", "Protagonist's Younger Sister as a Heroine":"妹妹女主角", "Life and Death Drama":"生死攸的戏剧", "Lactation During Sex":"做爱时泌乳", "Past":"游戏背景为过去", "Unlockable Routes":"可解锁路线", "Boy x Boy Romance":"男性和男性的恋爱", "Sex with Tentacles":"与触手做爱", "Monster Rape":"怪物强奸", "Sex with Others":"有角色和非主角的人做爱的场景", "Protagonist with Voice Acting":"有配音的主角", "Fighting Protagonist":"主角有武力", "Under the Same Roof":"同居", "Fan-fiction":"同人小说", "Sounds of Copulation":"做爱的音效", "Male on Male Sex":"男性对男性的性行为", "Dark Skinned Characters":"黑皮角色", "Christian Mythology":"基督教神话", "Gender Bending":"异装/跨性别", "Female Ejaculation":"潮吹", "Ahegao":"啊嘿颜", "Twin Blowjob":"两人共同口交", "Lolicon":"萝莉性爱场景和主题", "Single Handjob":"单人手交", "Tentacle Rape":"触手强奸", "Vaginal Fingering":"阴道指交", "Map Movement":"地图移动", "Reverse Cowgirl":"反转女上位体位", "Impregnation":"受精怀孕", "Protagonist's Blood-related Sister as a Heroine":"实姐实妹作为女主角", "Intercrural Sex":"跨性别做爱", "Game Jam":"游戏竞赛中开发", "More Than Seven Endings":"多于七个结局", "Simulation Game":"SLG", "Multiple Protagonists":"可选择多主角", "Photographic Assets":"静态资源", "Leader Heroine":"领导者女主角", "Blood-related Brother/Sister Incest":"血亲兄弟姐妹乱伦", "3D Graphics":"3D图形", "Slice of Life":"日常片段", "NVL":"文本占据大部分画面", "Horror":"恐怖", "Teacher Heroine":"教师女主角", "Combat":"搏斗", "Heroine with Health Issues":"有健康问题的女主角", "Photographic Backgrounds":"照片背景", "Married Heroine":"已婚女主角", "Sex Industry":"性产业", "Demons":"恶魔", "Anal Toys":"肛门玩具", "Sexual Slavery":"性奴隶", "Undead":"不死生物", "Single Footjob":"单人足交", "Few Choices":"选项少", "Gang Bang":"轮奸", "Heroine with Zettai Ryouiki":"有绝对领域的女主角", "Kemonomimi":"兽耳", "Protagonist's Full Sister as a Heroine":"同父同母的妹妹女主角", "Adult Hero":"成年人英雄", "Girl x Girl Romance":"女性和女性的恋爱", "Unavoidable Rape":"不可避的强奸剧情", "Magic":"魔法", "Non-human Protagonist":"非人类主角", "Perverted Heroine":"变态女主角", "Fictional World":"架空世界", "Colored Name-tags":"姓名彩色标识", "Sex in Water":"水中做爱", "Netorare":"NTR", "One True End":"唯一真结局", "Ponytail Heroine":"马尾女主角", "Threesome":"3p做爱", "Pre-rendered 3D Graphics":"非实时渲染3D", "Vaginal + Anal Penetration":"双重插入", "Vaginal Masturbation":"阴道/阴蒂自慰", "Domicile":"住所里", "Ojousama Heroine":"大小姐女主角", "Divine Heroine":"神话生物女主角", "Protagonist with Health Issues":"有健康问题的主角", "Bad Endings with Story":"BadEnd有剧情", "University Student":"大学生", "Non-blood-related Incest":"非血缘乱伦", "Dildos":"假阴茎" }, titleMap:{}, specialMap:{ /*匹配审批页*/ "^([A-Za-z \(\)]+?) /$":"%%$1%% /", }, }, { name:'评论|他人的评论列表', regular:/^\/w/i, map:{ /*列表页*/ "Type": "类型", "Review": "评论", "C#":"评论", "Last comment": "最后评论", "Full": "完全", "Mini": "迷你", /*评论详情页*/ "Was this review helpful?": "此评论对您有用吗?", "yes": "是", "no": "否", "Comments": "评论", }, titleMap:{}, specialMap:{ /*评论详情页*/ "Vote: (\\d+)": "评分: $1", "(\\d+) points": "$1个得分", }, }, { name:'封面插件翻译', regular:/^\/(v$|u\d+)/i, map:{ /*VNDB封面插件翻译*/ "Always Show the VN Info": "始终显示 VN 信息", "Show NSFW Covers": "显示 NSFW 封面", "Disable tooltip": "禁用工具提示", "Skip Additional Info": "跳过附加信息", "Async Cover": "异步封面", "Query Mode": "查询方式", "Legacy View": "旧版视图", /*封面上的文字*/ "Status:": "状态:", "Release(s):": "版本:", "Rating:": "评价:", "Cast date:": " 添加时间:", "No English translation": "没有英文翻译", "Has English translation": "有英文翻译", "Has partial English translation": "有部分英文翻译", "English translation planned":"有英语翻译的计划", "Translation Planned.":"翻译计划完成", "Translation Available.":"翻译可用", "No Translation Available":"没有可用的翻译", "Length unknown.": "长度未知.", "[ Read more... ]": "[阅读更多...]", }, titleMap:{}, specialMap:{}, }, { name:'规则说明', regular:/^\//i, map:{}, titleMap:{}, specialMap:{}, }, ]; /**-----------------------------业务逻辑部分[300行]----------------------------------*/ /** ---------------------------map处理---------------------------*/ let pathname = window.location.pathname; otherPageRules.forEach((item) => { //当regular是正则才执行 if (item.regular !== undefined && item.regular instanceof RegExp) { if (item.regular.test(pathname)) { //添加到主map,若存在重复项则覆盖主map Object.assign(mainMap, item.map); //添加特殊map Object.assign(specialMap, item.specialMap); //添加titleMap Object.assign(titleMap, item.titleMap); console.log(item.name + ',规则匹配:' + pathname + '->' + item.regular); } } }); /*object转Map, 正则new效率原因,先new出来*/ (function () { let tempMap = new Map(); let k = Object.getOwnPropertyNames(specialMap); for (let i = 0, len = k.length; i < len; i++) { try { tempMap.set(new RegExp(k[i]), specialMap[k[i]]); } catch (e) { console.log('"' + k[i] + '"不是一个合法正则表达式'); } } specialMap = tempMap; })(); /** ----------------------------END----------------------------*/ /** * 递归节点 * @param el 要处理的节点 * @param func 调用的函数 */ function 递归(el, func) { const nodeList = el.childNodes; /*先处理自己*/ 数据归一化(el,false); for (let i = 0; i < nodeList.length; i++) { const node = nodeList[i]; 数据归一化(node); } function 数据归一化(el,recursion=true) { if (el.nodeType === 1) { //为元素则递归 if (recursion){ 递归(el, func); } let attribute, value, flag = false; if (el.nodeName === 'INPUT') { value = el.getAttribute('value'); attribute = 'value'; if (value == null || value.trim().length === 0) { value = el.getAttribute('placeholder'); attribute = 'placeholder'; } flag = true; } else if (el.nodeName === 'TEXTAREA') { value = el.getAttribute('placeholder'); attribute = 'placeholder'; flag = true; } else if (el.getAttribute('title')!==null&& el.title.length!==0) { /*过判断用*/ value = 'title用过判断value值'; attribute = 'title'; flag = true; } if (!flag) return; func(el, value, attribute); } else if (el.nodeType === 3) { //为文本节点则处理数据 func(el, el.nodeValue); } } } recordsList = []; let observerMap = new Map(); /** * dom修改事件,包括属性,内容,节点修改 * @param document 侦听对象 * @param func 执行函数,可选参数(records),表示更改的节点 */ function dom修改事件(document, func) { const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;//浏览器兼容 const config = {attributes: true, childList: true, characterData: true, subtree: true};//配置对象 const observer = new MutationObserver(function (records, itself) { recordsList.push(records); //进入后停止侦听 let flag = false; let obsArr = []; let selfIndex = -1; let doc = -1; //找到当前对象对应的value,和索引,以及k for (let key of observerMap.keys()) { let t = observerMap.get(key); for (let i = 0; i < t.length; i++) { if (itself === t[i][0]) { obsArr = t; selfIndex = i; doc = key; flag = true; break; } } if (flag) { break; } } if (selfIndex === -1) { console.error('没有找到obs的v'); return; } /*停止与之相同config的obs*/ for (let i = 0; i < obsArr.length; i++) { if (JSON.stringify(obsArr[i][1]) === JSON.stringify(obsArr[selfIndex][1])) { obsArr[i][0].disconnect() } } /*调用与之相同config的obs*/ try { for (let i = 0; i < obsArr.length; i++) { if (JSON.stringify(obsArr[i][1]) === JSON.stringify(obsArr[selfIndex][1])) { obsArr[i][2](records); } } } catch (e) { console.error('执行错误') } //启用与之相同config的obs for (let i = 0; i < obsArr.length; i++) { if (JSON.stringify(obsArr[i][1]) === JSON.stringify(obsArr[selfIndex][1])) { obsArr[i][0].observe(doc, obsArr[i][1]); } } }); if (observerMap.get(document) !== undefined) { let v = observerMap.get(document); v.push([observer, config, func]); observerMap.set(document, v); } else { observerMap.set(document, [[observer, config, func]]); } /*开始侦听*/ observer.observe(document, config); } (function () { /*立即执行*/ console.time('初始原文化 ,时间'); 递归(document.body, 原文化); console.timeEnd('初始原文化 ,时间'); console.time('初始字典翻译,时间'); 递归(document.body, 字典翻译); console.timeEnd('初始字典翻译,时间'); /*当body发生变化时执行*/ dom修改事件(document.body, (records) => { console.time('原文化 ,时间'); for (let i = 0, len = records.length; i < len; i++) { 递归(records[i].target, 原文化); } console.timeEnd('原文化 ,时间'); console.time('字典翻译,时间'); for (let i = 0, len = records.length; i < len; i++) { 递归(records[i].target, 字典翻译); } console.timeEnd('字典翻译,时间'); }); function 原文化(node, value, attribute = 'Text') { if (value == null || value.trim().length === 0) return; value = value.trim(); if (attribute === 'Text') { let title = node.parentNode.getAttribute("title"); if (内容判定(title, value)) { node.parentNode.setAttribute("title", value); node.nodeValue = title; // console.log(value+'->'+title) } } else { let title = node.getAttribute("title"); if (内容判定(title, value)) { //若为通常节点则正常设置属性 node.setAttribute('title', value); node.setAttribute(attribute, title); // console.log(value+'->'+title) } } /** * 显示的部分不为中文或日文,并且交换的部分为中文或日文 * 且不应只有空格和> (标签链接浏览器页vn匹配) * 并且value没有对应翻译值,title没有翻译过[通过查找' \t\n'标记判断] * @param title * @param value * @returns {boolean} */ function 内容判定(title, value) { return title != null && !/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(value) && !/^[> ]+$/.test(value) && /[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(title) && mainMap[value]===undefined && title.indexOf(' \t\n')===-1; } } function 字典翻译(node, value, attribute = 'Text') { if (value == null || value.trim().length === 0) return; value = value.trim(); /** titleMap翻译*/ if (attribute==='title'){ if(mainMap[value] === undefined &&node.nodeType === 1&&node.title ){ /*如果为节点类型,value没有翻译,且存在title*/ let flag=true; /*判断子节点文本,若文本为中文日文或匹配mainMap或与title相等,则执行后续操作*/ let nodelist=node.childNodes; for (let i=0;i<nodelist.length;++i){ if (nodelist[i].nodeType===3&& (/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(nodelist[i].nodeValue) ||mainMap[nodelist[i].nodeValue] !== undefined ||node.title===nodelist[i].nodeValue) ){ flag=false; break; } } if (flag){/*加上翻译信息*/ if (titleMap[node.title] !== undefined) { node.title=titleMap[node.title]+" \t\n"+node.title; }else if (mainMap[node.title]!==undefined){ node.title=mainMap[node.title]+" \t\n"+node.title; } } } return; } /** mainMap翻译*/ if (mainMap[value] !== undefined) { if (attribute === 'Text') { //若为文本节点则追加父节点title属性 let title = node.parentNode.getAttribute('title'); if (title != null && title.trim() !== value) { node.parentNode.setAttribute('title', title + ' ' + value); } else { node.parentNode.setAttribute('title', value); } node.nodeValue = mainMap[value]; } else { //若为通常节点则正常设置属性 node.setAttribute('title', value); node.setAttribute(attribute, mainMap[value]) } }else { /** specialMap正则翻译*/ //遍历specialMap,正则替换 for (let key of specialMap.keys()) { /*正则匹配*/ if (key.test(value)) { /*正则替换*/ let newValue = value.replace(key, specialMap.get(key)); /*若有循环替换符,则进行替换*/ let nvs = newValue.split('%%'); /*如果map的值没有中文,且带%%%%,则设置flag为true*/ let flag = false; if (!/[\u4E00-\u9FA5]+/.test(specialMap.get(key)) && nvs.length !== 1 && nvs.length % 2 === 1) { flag = true; } if (nvs.length !== 1 && nvs.length % 2 === 1) { for (let i = 1; i < nvs.length; i += 2) { /*转小写*/ let low = nvs[i].split('@@'); if (low.length === 3) { nvs[i] = low[1].toLowerCase(); } /*匹配mainMap*/ if (mainMap[nvs[i]] !== undefined) { nvs[i] = mainMap[nvs[i]]; /*若找到map,则重新置flag为false*/ flag = false; } } newValue = nvs.join('') } if (flag) {/*如果替换式没有中文,且%%%%也没有匹配,则跳过*/ continue; } if (attribute === 'Text') { //若为文本节点则追加父节点title属性 let title = node.parentNode.getAttribute('title'); if (title != null && title.trim() !== value) { node.parentNode.setAttribute('title', title + ' ' + value); } else { node.parentNode.setAttribute('title', value); } node.nodeValue = newValue; } else { //若为通常节点则正常设置属性 node.setAttribute('title', value); node.setAttribute(attribute, newValue) } // console.log(value+'->'+newValue); /*替换后结束遍历*/ break; } } } } })(); /**-----------------------------开发用函数部分[350行]----------------------------------*/ /** 开启后通过控制台调用函数即可*/ let 开发者模式 = false; if (开发者模式) { /*exportMap已弃用*/ /** * 导出新的已被翻译的内容到控制台显示 * <br>即手动在网页上改文本,注意: * <br>先在要翻译的文本中间写入翻译后的内容 * <br>然后用del和backspace删除前后内容 * <br>开启编辑模式: * <br>document.body.contentEditable='true'; * <br>document.designMode='on'; */ exportMap = function () { let addMap = {}; 递归(document.body, 数据处理); /*导出到控制台处理*/ console.log(JSON.stringify(addMap)); function 数据处理(node, value, attribute = 'Text') { if (value == null || value.trim().length === 0) return; value = value.trim(); //没有在map中找到翻译 if (mainMap[value] === undefined) { //是中文、不是日文 if (/[\u4E00-\u9FA5]+/.test(value) && !/[ぁ-んァ-ヶ]+/.test(value)) { if (attribute === 'Text') { node = node.parentNode; } let title = node.getAttribute('title'); //如果title没有翻译,则记录 if (title !== null && mainMap[title] === undefined) { addMap[title] = value; } } } } }; /*** 记录所有满足条件的未翻译内容<br>缺点为找不到上下文*/ noMap = {}; /*** 记录所有满足条件的未翻译提示信息<br>缺点为找不到上下文*/ noTitleMap={}; /*** <s>用以复制value到title[已弃用]</s> * <br>现用来导出未翻译的title和value,map->控制台 * <br>若出现新元素,请手动通过控制台重新调用 * <br>若干扰项太多,可以通过删除干扰元素,再重新调用 * */ copyToTitle = () => { //清空 noMap = {}; noTitleMap={}; 递归(document.body, 数据处理); console.log(JSON.stringify(noMap)); console.log(JSON.stringify(noTitleMap)); function 数据处理(node, value, attribute = 'Text') { if (value == null || value.trim().length === 0) return; value = value.trim(); //没有在map中找到翻译 if (mainMap[value] === undefined) { //1<长度<300,不为中文、日文,不是纯数字 if (1 < value.length && value.length < 300 && !/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(value) && !/^[\d]+$/.test(value)) { //归一化处理 if (attribute === 'Text') { node = node.parentNode; } let title = node.getAttribute('title'); //title属性为中文或日文时不执行后续操作 if (title != null && /[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(title)) { return; } //未翻译的节点title if(title!= null&&titleMap[title]===undefined){ let flag=true; /*判断子节点文本,若文本为中文日文或匹配mainMap或与title相等,则不添加到未翻译title*/ let nodelist=node.childNodes; for (let i=0;i<nodelist.length;++i){ if (nodelist[i].nodeType===3&& (/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(nodelist[i].nodeValue) ||mainMap[nodelist[i].nodeValue] !== undefined ||title===nodelist[i].nodeValue) ){ flag=false; break; } } /*如果存在title,且title没有定义在mainMap*/ /*那么添加到待翻译title信息*/ if (flag){ noTitleMap[title] = title.toLowerCase(); } } //复制value->title // if (title != null && title.trim() !== value) { // node.setAttribute('title', title + ' ' + value); // } else { // node.setAttribute('title', value); // } //设置没有翻译的map标记 noMap[value] = value.toLowerCase(); } } } }; /*立即执行*/ copyToTitle(); /** *统计不应该匹配,但可以匹配的k->v与正则,用以将局部map升级到主map * @type {{Object}} */ otherLog = GM_getValue('otherLog') || {}; console.log(otherLog); delotherLog = () => { GM_deleteValue('otherLog'); }; /** * 按降序显示otherLog数组 */ showotherLog=()=>{ //复制一份 let temp=JSON.parse(JSON.stringify(otherLog)); let k = Object.getOwnPropertyNames(temp); let otherLogList=[]; for (let i = 0, len = k.length; i < len; i++) { temp[k[i]].unshift(k[i]); otherLogList.push(temp[k[i]]); } /*排序*/ otherLogList.sort(function (obj1, obj2) { return obj2[1] - obj1[1]; }); console.log(otherLogList); let sb='匹配项\t匹配数\t匹配时机\t匹配结果\n'; for (let i=0,len=otherLogList.length;i<len;i++){ sb+=otherLogList[i].join('\t')+'\n' } console.log(sb) }; /*未生效规则匹配测试,用以筛选常用规则手动上移至主规则*/ (() => { /*object转Map,将其他没有生效的map合起来*/ let otherMap = {}; let otherTitleMap={}; let otherSpecialMap = new Map(); otherPageRules.forEach((item) => { let pathname = window.location.pathname; if (item.regular !== undefined && item.regular instanceof RegExp && !item.regular.test(pathname)) { let k = Object.getOwnPropertyNames(item.specialMap); for (let i = 0, len = k.length; i < len; i++) { try { otherSpecialMap.set(new RegExp(k[i]), item.specialMap[k[i]]); } catch (e) { console.log('"' + k[i] + '"不是一个合法正则表达式'); } } Object.assign(otherMap, item.map); Object.assign(otherTitleMap, item.titleMap); } }); /*立即执行*/ console.time('初始其他规则,调试'); 递归(document.body, 未生效规则匹配测试); console.timeEnd('初始其他规则,调试'); /*当body发生变化时执行*/ dom修改事件(document.body, (records) => { console.time('其他规则,调试'); for (let i = 0, len = records.length; i < len; i++) { 递归(records[i].target, 未生效规则匹配测试); } console.timeEnd('其他规则,调试'); /*若不相等则更新并输出*/ if (JSON.stringify(otherLog) !== JSON.stringify(GM_getValue('otherLog') || {})) { GM_setValue('otherLog', otherLog); console.log(otherLog); } }); /** * 统计不应该匹配,但可以匹配的k->v与正则,用以将局部map升级到主map * @param key * @param value */ function otherLogAdd(key, value) { if (otherLog[key] === undefined) { otherLog[key] = [1, value[0], value[1]]; } else { let item = otherLog[key]; item[0]++; /*去重*/ let a1 = item[1].split('$$'); a1.push(value[0]); let mySet = new Set(a1); a1 = [...mySet]; item[1] = a1.join('$$'); a1 = item[2].split('$$'); a1.push(value[1]); mySet = new Set(a1); a1 = [...mySet]; item[2] = a1.join('$$'); } } function 未生效规则匹配测试(node, value, attribute = 'Text') { if (value == null || value.trim().length === 0) return; value = value.trim(); /*不被mainMap和specialMap匹配*/ /*由于执行顺序的原因,该判断基本没有意义*/ if (mainMap[value] !== undefined) { return; } /*因为正则涉及匹配可能太广,所以不排除*/ // for (let key of specialMap.keys()) { // if (key.test(value)) { // return; // } // } /*1<长度<300,不为中文、日文,不是纯数字,降低缩进*/ let f = true; if (1 < value.length && value.length < 300 && !/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(value) && !/^[\d]+$/.test(value)) { f = false; } if (f) return; /*title翻译*/ /** titleMap翻译*/ if (attribute==='title'){ if(otherMap[value] === undefined &&node.nodeType === 1&&node.title ){ /*如果为节点类型,value没有翻译,且存在title*/ let flag=true; /*判断子节点文本,若文本为中文日文或匹配mainMap或与title相等,则执行后续操作*/ let nodelist=node.childNodes; for (let i=0;i<nodelist.length;++i){ if (nodelist[i].nodeType===3&& (/[\u4E00-\u9FA5ぁ-んァ-ヶ]+/.test(nodelist[i].nodeValue) ||otherMap[nodelist[i].nodeValue] !== undefined ||node.title===nodelist[i].nodeValue) ){ flag=false; break; } } if (flag){/*加上翻译信息*/ let title=node.title; if (otherTitleMap[title] !== undefined) { node.title=otherTitleMap[title]+" \t\n"+title; otherLogAdd(title, ['otherTitleMap匹配', otherTitleMap[title]]); }else if (otherMap[node.title]!==undefined){ node.title=otherMap[title]+" \t\n"+title; otherLogAdd(title, ['otherTitleMap->otherMap匹配', otherMap[title]]); } } } return; } if (otherMap[value] !== undefined) { if (attribute === 'Text') { //若为文本节点则追加父节点title属性 let title = node.parentNode.getAttribute('title'); if (title != null && title.trim() !== value) { node.parentNode.setAttribute('title', title + ' ' + value); } else { node.parentNode.setAttribute('title', value); } node.nodeValue = otherMap[value]; otherLogAdd(value, ['otherMap匹配,Text', otherMap[value]]); } else { //若为通常节点则正常设置属性 node.setAttribute('title', value); node.setAttribute(attribute, otherMap[value]); otherLogAdd(value, ['otherMap匹配,节点', otherMap[value]]); } } else { //遍历specialMap,正则替换 for (let key of otherSpecialMap.keys()) { /*正则匹配,降低缩进*/ if (!key.test(value)) {continue;} let info = 'otherSpecialMap匹配,正则:' + key + ','; /*正则替换*/ let newValue = value.replace(key, otherSpecialMap.get(key)); /*若有循环替换符,则进行替换*/ let nvs = newValue.split('%%'); /*如果map的值没有中文,且带%%%%,则设置flag为true*/ let flag = false; if (!/[\u4E00-\u9FA5]+/.test(otherSpecialMap.get(key)) && nvs.length !== 1 && nvs.length % 2 === 1) { flag = true; } if (nvs.length !== 1 && nvs.length % 2 === 1) { for (let i = 1; i < nvs.length; i += 2) { /*转小写*/ let low = nvs[i].split('@@'); if (low.length === 3) { nvs[i] = low[1].toLowerCase(); } /*匹配otherMap*/ if (otherMap[nvs[i]] !== undefined) { nvs[i] = otherMap[nvs[i]]; info += '在otherMap找到%%%%(额外匹配),'; /*若找到map,则重新置flag为false*/ flag = false; } /*匹配匹配mainMap*/ if (mainMap[nvs[i]] !== undefined) { nvs[i] = mainMap[nvs[i]]; info += '在mainMap找到%%%%(额外匹配),'; /*若找到map,则重新置flag为false*/ flag = false; } } newValue = nvs.join('') } /*如果替换式没有中文,且%%%%也没有匹配,则跳过*/ if (flag) {continue;} if (attribute === 'Text') { //若为文本节点则追加父节点title属性 let title = node.parentNode.getAttribute('title'); if (title != null && title.trim() !== value) { node.parentNode.setAttribute('title', title + ' ' + value); } else { node.parentNode.setAttribute('title', value); } node.nodeValue = newValue; info += 'Text'; } else { //若为通常节点则正常设置属性 node.setAttribute('title', value); node.setAttribute(attribute, newValue); info += '节点'; } otherLogAdd(value, [info, newValue]); // console.log(value + '->' + newValue); /*替换后结束遍历*/ break; } } } })(); }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址