您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
中文化 Hugging Face 界面的菜单及内容
// ==UserScript== // @name Hugging Face 中文化插件 // @namespace https://github.com/your-username/hf-chinese // @description 中文化 Hugging Face 界面的菜单及内容 // @copyright 2025 // @icon https://huggingface.co/front/assets/huggingface_logo-noborder.svg // @version 1.0.2 // @author 蛋定的文弱书生 // @license GPL-3.0 // @match https://huggingface.co/* // @match https://*.huggingface.co/* // @run-at document-end // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_notification // @grant GM_getValue // @grant GM_setValue // @supportURL https://github.com/1972074121/Youhou/issues // ==/UserScript== (function (window, document, undefined) { 'use strict'; // 语言设置 const lang = 'zh'; // 词库配置 const I18N = { zh: { // 公共词库(所有页面通用) public: { static: { // 导航栏 "Models": "模型", "Datasets": "数据集", "Spaces": "空间", "Docs": "文档", "Solutions": "解决方案", "Pricing": "价格", "Sign in": "登录(不可用)", "Sign Up": "注册(不可用)", "Search": "搜索", // 侧边栏 "Filters": "筛选器", "All": "全部", "Text": "文本", "Image": "图像", "Audio": "音频", "Video": "视频", "Multimodal": "多模态", "Table": "表格", "Fill-Mask": "掩码填充", "Token Classification": "标记分类", "Text Generation": "文本生成", "Text2Text Generation": "文本到文本生成", "Summarization": "摘要生成", "Conversational": "对话", "Feature Extraction": "特征提取", "Translation": "翻译", "Multiple Choice": "多项选择", "Text Classification": "文本分类", "Question Answering": "问答", "Sentence Similarity": "句子相似度", "Zero-Shot Classification": "零样本分类", "Enterprise": "企业版", "Audio-Text-to-Text": "音频文本转文本", "Image-Text-to-Text": "图像文本转文本", "Visual Question Answering": "视觉问答", "Document Question Answering": "文档问答", "Video-Text-to-Text": "视频文本转文本", "Visual Document Retrieval": "视觉文档检索", "Any-to-Any": "任意到任意", "Computer Vision": "计算机视觉", "Depth Estimation": "深度估计", "Image Classification": "图像分类", "Object Detection": "目标检测", "Image Segmentation": "图像分割", "Text-to-Image": "文本到图像", "Image-to-Text": "图像到文本", "Image-to-Image": "图像到图像", "Image-to-Video": "图像到视频", "Unconditional Image Generation": "无条件图像生成", "Video Classification": "视频分类", "Text-to-Video": "文本到视频", "Zero-Shot Image Classification": "零样本图像分类", "Mask Generation": "掩码生成", "Zero-Shot Object Detection": "零样本目标检测", "Text-to-3D": "文本到3D", "Image-to-3D": "图像到3D", "Image Feature Extraction": "图像特征提取", "Keypoint Detection": "关键点检测", "Natural Language Processing": "自然语言处理", "Table Question Answering": "表格问答", "Text Ranking": "文本排序", "Text-to-Speech": "文本到语音", "Text-to-Audio": "文本到音频", "Automatic Speech Recognition": "自动语音识别", "Audio-to-Audio": "音频到音频", "Audio Classification": "音频分类", "Voice Activity Detection": "语音活动检测", "Tabular": "表格数据", "Tabular Classification": "表格分类", "Tabular Regression": "表格回归", "Time Series Forecasting": "时间序列预测", "Reinforcement Learning": "强化学习", "Robotics": "机器人学", "Other": "其他", "Graph Machine Learning": "图机器学习", // 按钮 "Load more": "加载更多", "Subscribe": "订阅", "Download": "下载", "Upload": "上传", "Create": "创建", "Settings": "设置", "Profile": "个人资料", "Logout": "退出登录(不可用)", // 模型卡片 "Model card": "模型卡片", "Files and versions": "文件与版本", "Community": "社区", "Training metrics": "训练指标", "Training logs": "训练日志", "Deploy": "部署", "Use in Transformers": "在Transformers中使用", "Hosted inference API": "托管推理API", "Contributors": "贡献者", "License": "许可证", // 空间相关 "Duplicate this Space": "复制此空间", "Embed this Space": "嵌入此空间", "App": "应用", "Files": "文件", "Sessions": "会话", "Hardware": "硬件", "Storage": "存储", "Variables": "变量", "Logs": "日志", // 文档 "Previous": "上一页", "Next": "下一页", "On this page": "本页内容", "Table of contents": "目录", "Getting Started": "入门指南", "Tutorials": "教程", "Conceptual Guides": "概念指南", "How-to Guides": "操作指南", "API Documentation": "API文档", // 新增翻译内容 "Tasks": "任务", "Libraries": "库", "Languages": "语言", "Licenses": "许可证", "Website": "网站", "HuggingChat": "Hugging聊天", "Collections": "收藏集", "Organizations": "组织", "Blog": "博客", "Posts": "帖子", "Daily Papers": "每日论文", "Learn": "学习", "Discord": "Discord社区", "Forum": "论坛", "Github": "GitHub", "Enterprise Hub": "企业中心", "Expert Support": "专家支持", "Inference Endpoints": "推理端点", "Notifications": "通知", "Inbox": "收件箱", "New Model": "新建模型", "New Dataset": "新建数据集", "New Space": "新建空间", "New Collection": "新建收藏集", "Create organization": "创建组织", "Usage Quota": "使用配额", "Private Storage": "私有存储", "Zero GPU": "零GPU", "Inference Usage": "推理使用量", "Subscribe to PRO": "订阅PRO版", "Access Tokens": "访问令牌", "Billing": "账单", "Changelog": "更新日志", "Sign Out": "退出登录(不可用)", "AI & ML interests": "AI与ML兴趣", "Recent Activity": "最近活动", "Account": "账户", "Authentication": "认证", "SSH and GPG Keys": "SSH和GPG密钥", "Inference Providers": "推理提供商", "Webhooks": "Webhooks", "Papers": "论文", "Local Apps and Hardware": "本地应用与硬件", "Gated Repositories": "受限仓库", "Content Preferences": "内容偏好", "Connected Apps": "已连接应用", "Theme": "主题", "Discussions": "讨论", "Pull requests": "拉取请求", "Welcome to the community": "欢迎来到社区专区", "The community tab is the place to discuss and collaborate with the HF community!": "此处是您与 HF 社区交流协作的专属空间!", "New discussion": "发起新讨论", "New pull request": "创建拉取请求", "Watch all activity": "查看所有活动动态", "View closed": "查看已关闭项", "Discussions": "讨论", "Short": "排序", "Recently created": "最近创建", "Most reactions": "最多互动", "Trending": "热门内容", "Filter by title": "按标题筛选", "Resources": "资源", "Search models, datasets, users...": "搜索模型、数据集、用户...", "No model card": "无模型卡片", "New: Create and edit this model card directly on the website!": "新功能:直接在线创建并编辑模型卡片!", "Contribute a Model Card": "贡献模型卡片", "Adapters": "适配器", "Finetunes": "微调模型", "Merges": "合并模型", "Quantizations": "量化模型" }, regexp: [ // 正则替换规则 [/(\d+) days? ago/, '$1天前'], [/(\d+) hours? ago/, '$1小时前'], [/(\d+) minutes? ago/, '$1分钟前'], [/Just now/, '刚刚'], [/(\d+) downloads?/, '$1次下载'], [/(\d+) likes?/, '$1个点赞'], [/View closed (\d+)?/, '查看已关闭项 $1'], ] }, // 主页特定词库 homepage: { static: { "Models, datasets and Spaces": "模型、数据集与空间", "Discover, explore and share ML resources": "发现、探索并分享机器学习资源", "Trending": "热门", "New": "最新", "Top": "最佳", "Top contributors": "顶级贡献者", "Featured Spaces": "精选空间", "All Spaces": "所有空间", "Explore": "探索", "Browse models": "浏览模型", "Browse datasets": "浏览数据集", "Browse Spaces": "浏览空间", } }, // 模型列表页 models: { static: { "Browse models": "浏览模型", "Sort:": "排序:", "Most likes": "最多点赞", "Most downloads": "最多下载", "Recently updated": "最近更新", "Task": "任务", "Library": "库", "Dataset": "数据集", "Architecture": "架构", "Languages": "语言", "Licenses": "许可证", "Model name or keyword": "模型名称或关键词", "Search models": "搜索模型", } }, // 数据集列表页 datasets: { static: { "Browse datasets": "浏览数据集", "Sort:": "排序:", "Most likes": "最多点赞", "Most downloads": "最多下载", "Recently updated": "最近更新", "Task": "任务", "Library": "库", "Language": "语言", "Licenses": "许可证", "Dataset name or keyword": "数据集名称或关键词", "Search datasets": "搜索数据集", } }, // 空间列表页 spaces: { static: { "Browse Spaces": "浏览空间", "Sort:": "排序:", "Most likes": "最多点赞", "Recently updated": "最近更新", "SDK": "SDK", "Hardware": "硬件", "License": "许可证", "Space name or keyword": "空间名称或关键词", "Search Spaces": "搜索空间", } }, // 文档页 docs: { static: { "Hugging Face Documentation": "Hugging Face 文档", "Search the docs": "搜索文档", "Edit this page": "编辑此页", "Feedback": "反馈", } }, // 模型详情页 model_detail: { static: { "Model description": "模型描述", "Intended uses & limitations": "预期用途与限制", "How to use": "如何使用", "Limitations and bias": "限制与偏见", "Training data": "训练数据", "Training procedure": "训练过程", "Evaluation results": "评估结果", "Citation": "引用", "Model card authors": "模型卡片作者", "Model card contributors": "模型卡片贡献者", } }, // 空间详情页 space_detail: { static: { "Running on": "运行于", "Last updated": "最后更新", "Created by": "创建者", "App files": "应用文件", "README.md": "自述文件", } } } }; // 全局变量 let page; let enable_RegExp = GM_getValue("enable_RegExp", 1); /** * watchUpdate 函数:监视页面变化,根据变化的节点进行翻译 */ function watchUpdate() { // 检测浏览器是否支持 MutationObserver const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; // 获取当前页面的 URL const getCurrentURL = () => location.href; getCurrentURL.previousURL = getCurrentURL(); // 创建 MutationObserver 实例,监听 DOM 变化 const observer = new MutationObserver((mutations, observer) => { const currentURL = getCurrentURL(); // 如果页面的 URL 发生变化 if (currentURL !== getCurrentURL.previousURL) { getCurrentURL.previousURL = currentURL; page = getPage(); // 当页面地址发生变化时,更新全局变量 page console.log(`链接变化 page= ${page}`); if (page) { setTimeout(() => { // 重新翻译页面 traverseNode(document.body); }, 500); } } if (page) { // 使用 filter 方法对 mutations 数组进行筛选, // 返回 `节点增加、文本更新 或 属性更改的 mutation` 组成的新数组 filteredMutations。 const filteredMutations = mutations.filter(mutation => mutation.addedNodes.length > 0 || mutation.type === 'attributes' || mutation.type === 'characterData'); // 处理每个变化 filteredMutations.forEach(mutation => traverseNode(mutation.target)); } }); // 配置 MutationObserver const config = { characterData: true, subtree: true, childList: true, attributeFilter: ['value', 'placeholder', 'aria-label', 'data-confirm'], // 仅观察特定属性变化 }; // 开始观察 document.body 的变化 observer.observe(document.body, config); } /** * traverseNode 函数:遍历指定的节点,并对节点进行翻译。 * @param {Node} node - 需要遍历的节点。 */ function traverseNode(node) { // 跳过忽略 if (node.id && /react-.*|notification|toast|modal|dialog/i.test(node.id)) { return; } if (node.nodeType === Node.ELEMENT_NODE) { // 元素节点处理 // 元素节点属性翻译 if (["INPUT", "TEXTAREA"].includes(node.tagName)) { // 输入框 按钮 文本域 if (["button", "submit", "reset"].includes(node.type)) { transElement(node, 'value'); } else { transElement(node, 'placeholder'); } } else if (node.tagName === 'BUTTON') { if (node.hasAttribute('aria-label')) { transElement(node, 'aria-label', true); } if (node.hasAttribute('title')) { transElement(node, 'title', true); } if (node.hasAttribute('data-confirm')) { transElement(node, 'data-confirm', true); } } else if (node.tagName === 'OPTGROUP') { // 翻译 <optgroup> 的 label 属性 transElement(node, 'label'); } else if (node.tagName === 'A') { if (node.hasAttribute('title')) { transElement(node, 'title', true); } } let childNodes = node.childNodes; childNodes.forEach(traverseNode); // 遍历子节点 } else if (node.nodeType === Node.TEXT_NODE) { // 文本节点翻译 if (node.length <= 500) { transElement(node, 'data'); } } } /** * getPage 函数:获取当前页面的类型。 * @returns {string|boolean} 当前页面的类型,如果无法确定类型,那么返回 false。 */ function getPage() { const pathname = location.pathname; // 当前路径 // 根据路径判断页面类型 if (pathname === '/') { return 'homepage'; } else if (pathname.startsWith('/models')) { return pathname.split('/').length > 2 ? 'model_detail' : 'models'; } else if (pathname.startsWith('/datasets')) { return pathname.split('/').length > 2 ? 'dataset_detail' : 'datasets'; } else if (pathname.startsWith('/spaces')) { return pathname.split('/').length > 2 ? 'space_detail' : 'spaces'; } else if (pathname.startsWith('/docs')) { return 'docs'; } else if (pathname.split('/').length === 2) { // 例如:/username/modelname return 'model_detail'; } // 默认使用公共词库 return 'public'; } /** * transElement 函数:翻译指定元素的文本内容或属性。 * @param {Element} el - 需要翻译的元素。 * @param {string} field - 需要翻译的文本内容或属性的名称。 * @param {boolean} isAttr - 是否需要翻译属性。 */ function transElement(el, field, isAttr = false) { let text = isAttr ? el.getAttribute(field) : el[field]; // 需要翻译的文本 if (!text) return; let str = translateText(text); // 翻译后的文本 // 替换翻译后的内容 if (str) { if (!isAttr) { el[field] = str; } else { el.setAttribute(field, str); } } } /** * translateText 函数:翻译文本内容。 * @param {string} text - 需要翻译的文本内容。 * @returns {string|boolean} 翻译后的文本内容,如果没有找到对应的翻译,那么返回 false。 */ function translateText(text) { // 内容为空, 空白字符和或数字, 不存在英文字母和符号,. 跳过 if (!text || !/[a-zA-Z,.]+/.test(text)) { return false; } let _key = text.trim(); // 去除首尾空格的 key let _key_neat = _key.replace(/\xa0|[\s]+/g, ' '); // 去除多余空白字符( 空格 换行符) let str = fetchTranslatedText(_key_neat); // 翻译已知页面 (局部优先) if (str && str !== _key_neat) { // 已知页面翻译完成 return text.replace(_key, str); // 替换原字符,保留首尾空白部分 } return false; } /** * fetchTranslatedText 函数:从特定页面的词库中获得翻译文本内容。 * @param {string} key - 需要翻译的文本内容。 * @returns {string|boolean} 翻译后的文本内容,如果没有找到对应的翻译,那么返回 false。 */ function fetchTranslatedText(key) { // 静态翻译 let str = (I18N[lang][page]?.static?.[key]) || (I18N[lang].public?.static?.[key]); // 默认翻译 公共部分 if (typeof str === 'string') { return str; } // 正则翻译 if (enable_RegExp) { let res = (I18N[lang][page]?.regexp || []).concat(I18N[lang].public?.regexp || []); // 正则数组 for (let [a, b] of res) { try { let regex = new RegExp(a, 'g'); if (regex.test(key)) { return key.replace(regex, b); } } catch (e) { console.error('正则表达式错误:', a, e); } } } return false; // 没有翻译条目 } function registerMenuCommand() { const toggleRegExp = () => { enable_RegExp = !enable_RegExp; GM_setValue("enable_RegExp", enable_RegExp); GM_notification(`已${enable_RegExp ? '开启' : '关闭'}正则功能`); GM_unregisterMenuCommand(id); id = GM_registerMenuCommand(`${enable_RegExp ? '关闭' : '开启'}正则功能`, toggleRegExp); // 刷新页面以应用更改 location.reload(); }; let id = GM_registerMenuCommand(`${enable_RegExp ? '关闭' : '开启'}正则功能`, toggleRegExp); } /** * init 函数:初始化翻译功能。 */ function init() { // 获取当前页面的翻译规则 page = getPage(); console.log(`开始page= ${page}`); if (page) { // 立即翻译页面 traverseNode(document.body); } // 监视页面变化 watchUpdate(); // 添加菜单命令 registerMenuCommand(); } // 执行初始化 setTimeout(init, 1000); })(window, document);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址