GreasyFork 中文

实验性脚本, 尚有内容未翻译完毕。

Ajankohdalta 12.6.2014. Katso uusin versio.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        GreasyFork 中文
// @namespace   http://jixun.org/
// @description 实验性脚本, 尚有内容未翻译完毕。
// @include     https://greatest.deepsurf.us/*
// @version     1.1
// @run-at      document-start
// @grant       none
// ==/UserScript==

var translation = {
	// Links
	'a': {
		'Back': '返回',
		'Post a new script': '提交新脚本',
		'Attach a file': '上传附件'
	},

	'h1,h2,h3': {
		'Scripts': '脚本',
		'Recent Discussions': '近期讨论',

		// 论坛
		'Comments': '吐槽',
		'Leave a Comment': '发表回复'
	},

	// 右上角 - 搜索框
	'#script-search': {
		'Search': '搜索脚本'
	},

	// 右上角导航条
	'#main-header>nav': {
		'Scripts': '脚本列表',
		'Forum': '论坛',
		'Help': '帮助',
		'Search': '搜索脚本'
	},

	// 用户页面 - 控制面板
	'#control-panel': {
		'Control panel': '控制台',
		'Post a script': '提交脚本',
		'Import scripts': '批量导入脚本',
		'Set up a GitHub webhook': '设定 GitHub WebHook (自动更新)',
		'Edit account': '更改账户信息',
		'Sign out': '登出系统'
	},

	// 用户页面 - 讨论组
	'#user-discussions-on-scripts-written': {
		__regex: [
			[/(\d+) minutes? ago/, '发表于 $1 分钟前'],
			[/(\d+) hours? ago/, '发表于 $1 小时前'],
			[/(\d+) days? ago/, '发表于 $1 天前']
		],
		'Discussions on your scripts': '您的脚本讨论帖 ',
		'More discussions': '> 点我查看更多讨论贴',
		', last comment by': ',最后评论由 ',
		'by': ' 由 ',
	},

	// 用户页面 & 检索页面 的脚本列表
	'.script-list': {
		__regex: [
			[/(\d+) minutes? ago/, '$1 分钟前'],
			[/(\d+) hours? ago/, '$1 小时前'],
			[/(\d+) days? ago/, '$1 天前']
		],
		'Author': '脚本作者',
		'Daily installs': '今日安装',
		'Total installs': '安装总数',
		'Created': '创建日期',
		'Updated': '更新日期',
		'(Deleted)': '(已删)',
		'(Locked)': '(锁定)'
	},

	// 脚本检索页 - 排序
	'#script-list-sort': {
		'Daily installs': '今日安装',
		'Total installs': '安装总数',
		'Sort by:': '排序方式: ',
		'Created date': '创建日期',
		'Updated date': '更新日期',
	},

	// 脚本检索页 - 过滤
	'#script-list-filter': {
		'Showing:': '显示: ',
		'All': '所有脚本',
		'(All sites)': '(全部网站)',
		'More...': '更多…',
		'Search': '搜索',
		'Applies to': '应用于',
		'All sites': '所有站点'
	},

	// 翻页
	'.pagination': {
		'← Previous': '← 上一页',
		'Next →': '下一页 →'
	},

	// 脚本信息页 - 导航标签
	'#script-links': {
		__regex: [
			[/Feedback \((\d+)\)/, '反馈与吐槽 ($1)'],
		],
		'Info': '脚本信息',
		'Code': '参阅源码',
		'History': '更新历史',
		'Update': '更新脚本',
		'Sync': '同步',
		'Delete': '删除脚本',
		'Undelete': '取消删除',
	},

	// 脚本信息页 - 脚本简介
	'#script-content': {
		'Install this script': '安装该脚本',
		'Version': '版本',
		'Author': '作者',
		'Daily installs': '今日安装',
		'Total installs': '安装总数',
		'Created': '创建日期',
		'Updated': '更新日期',
		'License': '脚本授权',
		'N/A': '未知',
		'Applies to': '脚本运行于下述站点',
		'Author\'s Description': '脚本详细描述',
		'Diff': '查询更改'
	},

	// 脚本更新页 - 代码规则
	'#script-content>p': {
		'Scripts must be': '请注意: 您所上传的脚本应',
		'properly described': '代码、思路清晰',
		', cannot be': ',不得',
		'obfuscated': '加密',
		'or': '或',
		'minified': '压缩',
		', must respect': ',必须尊重第三方',
		'copyright': '版权',
		', and are limited in the': ',以及确保引用的',
		'external code': '外部代码',
		'used.': '不在白名单之外。',
		'Read the full rules.': '查阅完整脚本发布规则 (英文)'
	},

	// 脚本更新页 - 代码发布框
	'#script-content>#new_script_version': {
		'Code': '提交代码',
		'Or upload:': '或直接上传:',
		'Script type': '脚本类型',

		// 脚本类型
		'Public user script - A user script for all to see and use.': '公开用户脚本 - 所有用户均可视及安装、更新',
		'Unlisted user script - A user script for (semi-)private use. Available by direct access, but not linked to from anywhere on Greasy Fork.': '私用脚本 - 私用脚本,仅限拥有链接的用户可以访问 (不需要登录)。',
		'Library - A script intended to be @require-d from other scripts and not installed directly.': '脚本库 - 用于第三方 @require 引用',

		'Additional info': '脚本详细描述',
		'Ramble on about your script.': '脚本的那点事',
		'Preview': '预览',
		'Post new version': '发布新版'
	},

	// Feedback 标签页
	'#no-discussions': {
		'No discussions posted yet.': '尚无该脚本相关评论,',
		'Be the first to discuss this script.': '戳我抢下第一贴!',
		'Start a new discussion on this script.': '想吐槽?点我发布到论坛~'
	},

	// 用户信息 - 更改页
	'#edit_user': {
		'Name': '用户名',
		'Email': '邮件',
		'Profile': '个人信息',
		'Preview': '预览',
		'Password': '密码',
		'(Leave blank if you don\'t want to change it)': '(如果不想更改请留空)',
		'Password confirmation': '密码确认',
		'Current password': '当前密码',
		'(We need your current password to confirm your changes)': '(请输入当前密码确认信息更新)',
		'Update': '更新'
	},

	// 论坛 - 右上角搜索框
	'.SiteSearch': {
		'Search': '搜索论坛'
	},

	// 论坛 - 上方导航
	'.SiteMenu': {
		'Discussions': '讨论区',
		'Activity': '论坛动态',
		'Mark All Viewed': '全部标为已阅'
	},

	// 论坛 - 发帖按钮
	'.Button': {
		'New Discussion': '发表新帖',
		'Preview': '预览',
		'Save Draft': '储存草稿',
		'Post Comment': '发表回复'
	},

	// 论坛 - 左边过滤
	'.BoxFilter': {
		'Categories': '论坛板块',
		'Recent Discussions': '近期讨论',
		'Activity': '论坛活动',
		'My Discussions': '我的帖子',
		'My Drafts': '我的草稿',
		'Discussions': '帖子',
		'Comments': '帖子回应'
	},

	// 论坛 - 板块名称
	'.BoxCategories,.Meta>.Category': {
		'Categories': '论坛板块',
		'All Categories': '所有板块',
		'Greasy Fork Meta': '站点相关',
		'Script Development': '脚本开发',
		'Script Requests': '脚本请求',
		'Script Discussions': '脚本讨论'
	},

	// 论坛 - 帖子操作
	'.OptionsMenu': {
		'Edit': '编辑',
		'Delete': '删除'
	},

	// 论坛 - 其他
	'.Meta': {
		__regex: [
			[/edited(.+)/, '最后编辑于$1']
		],
		'Announcement': '公告',
		'views': ' 次围观',
		'comments': ' 个吐槽',
		'comment': ' 个吐槽',
		'Most recent by': '最新吐槽 by '
	},

	// 论坛 - 帖子链接
	'.MItem': {
		'in': '发布于 ',
		'Flag': '举报',
		'Quote': '引用'
	},


	// 论坛 - 菜单
	'.MenuItems': {
		'Preferences': '首选项',
		'Mark All Viewed': '全部标为已阅',
		'Sign Out': '登出论坛'
	},

	// 论坛 - 私信按钮
	'.ProfileOptions': {
		'Message': '私信'
	},

	// 论坛 - 各类窗口
	'.PopList': {
		__regex: [
			[/(\d+) messages?/, '$1 条内容']
		],

		'Notifications': '通知',
		'Notification Preferences': '设定',
		'mentioned you in': ' 提到你:',
		'All Notifications': '所有通知',

		'Inbox': '私信',
		'New Message': '撰写私信',
		'All Messages': '所有私信'
	}
};

var _each = function (arr, eachCb, defValue) {
	if (!arr || !arr.length) return ;

	for (var i = arr.length, ret; i-- ; )
		// If there's something to return, then return it.
		if (ret = eachCb (arr[i], i))
			return ret;

	return defValue ;
};

var doesNodeMatch = (function (doc) {
	var matches = doc.matches || doc.mozMatchesSelector || doc.oMatchesSelector || doc.webkitMatchesSelector;

	return matches ? function (what, selector) {
		return matches.call (what, selector);
	} : function () {
		// No matche selector :<
		return false;
	};
}) (document.documentElement);

// 寻找翻译
var findTranslation = function (domSelector, origionalContent) {
	// Not string or undefined etc.
	if (!origionalContent) return null;

	var tmpNodeContent    = origionalContent.trim(),
		translatedContent = translation[domSelector][tmpNodeContent];

	// Empty string.
	if (!tmpNodeContent) return origionalContent;

	// Language string match!
	if (translatedContent) return translatedContent;

	// Check weather it has regex matches.
	if (!translation[domSelector].hasOwnProperty('__regex')) return null;

	// Check regex match.
	return _each (translation[domSelector].__regex, function (regex) {
		if (regex[0].test (tmpNodeContent))
			return String.prototype.replace.apply (tmpNodeContent, regex);
	});
};

var fixInput = function (domSelector, inputDom) {
	// 搜索框
	if (translatedContent = findTranslation(domSelector, inputDom.getAttribute ('placeholder') || ''))
		inputDom.setAttribute ('placeholder', translatedContent);

	// 提交按钮
	if (translatedContent = findTranslation(domSelector, inputDom.value || ''))
		inputDom.value = translatedContent;
};

var translateNode = function (domSelector, domNode) {
	console.log ('translateNode: %s', domSelector);
	try {
		// Fix input element
		if (domNode.nodeName == 'INPUT') {
			fixInput (domSelector, domNode);
			return ;
		}

		// Loop through all text nodes:
		// http://stackoverflow.com/a/2579869/3416493
		var walker = document.createTreeWalker(domNode, NodeFilter.SHOW_TEXT, null, false),
			node, translatedContent;

		// Loop through text nodes.
		while (node = walker.nextNode())
			if (translatedContent = findTranslation (domSelector, node.nodeValue))
				node.nodeValue = translatedContent;

		// Loop through inputs.
		_each (domNode.getElementsByTagName ('input'), fixInput.bind({}, domSelector));
	} catch (e) {
		console.error ('translateNode: ', e);
	}
}

var translateContent = function (domSelector, base) {
	console.log ('translateContent: %s', domSelector);
	_each (base.querySelectorAll (domSelector), translateNode.bind({}, domSelector));
};

var cbTranslate = function (base) {
	try {
		console.log (base);
		for (var x in translation) {
			if (translation.hasOwnProperty (x)) {
				if (doesNodeMatch (base, x)) {
					console.info ('%s matches!', x);
					translateNode (x, base);
				} else {
					translateContent (x, base);
				}
			}
		}
	} catch (e) {
		console.error ('cbTranslate error:', e);
	}
};

var mo = new MutationObserver (function (m) {
	_each (m, function (q) {
		_each (q.addedNodes, function (e) {
			// Ignore firebug
			if (e.className.indexOf ('firebug') != -1) return ;

			cbTranslate (e);
		});
	});
});

mo.observe (document, {
	childList: true,
	subtree: true
});

addEventListener ('DOMContentLoaded', function () {
	cbTranslate (document.body);
}, false);