NotionChinese

Notion Sinicization

  1. // ==UserScript==
  2. // @name NotionChinese
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Notion Sinicization
  6. // @author Leon
  7. // @match *://www.notion.so/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. function I18N() {
  15. this.lang = 'en';
  16. }
  17.  
  18. I18N.prototype.install = function(langName, keymap){
  19. if (this[langName] === undefined) {
  20. this[langName] = keymap;
  21. }
  22. };
  23.  
  24. const I18n = new I18N();
  25.  
  26. I18n.install('zh', {
  27. // 左边栏
  28. 'Create or Join Workspace': '创建或加入工作区',
  29. 'Log Out (': '注销 (',
  30. 'Quick Find': '快速查找',
  31. 'All Updates': '所有的更新',
  32. 'Followed': '已关注',
  33. 'Mentions': '提到我的',
  34. 'Open notifications settings': '打开消息设置',
  35. 'Settings & Members': '设置 & 成员',
  36. 'Templates': '模板',
  37. 'Import': '导入',
  38. 'Trash': '垃圾桶',
  39. 'New Page': '新建页面',
  40.  
  41. // 右边栏顶栏
  42. 'Share': '分享',
  43. 'Updates': '更新',
  44. 'Favorite': '喜欢',
  45.  
  46. // 块选项
  47. 'Add Icon': '添加图标',
  48. 'Add Cover': '添加封面',
  49. 'Add Discussion': '添加议题',
  50. 'Drag': '拖动',
  51. 'Click': '点击',
  52. 'to move': '来移动行',
  53. 'to open menu': '打开菜单',
  54. 'to add a block below': '在下方添加一个编辑块',
  55. 'Rename, delete, and more...': '重命名,删除,及更多...',
  56. 'Change icon': '改变图标',
  57. 'Delete': '删除',
  58. 'Duplicate': '重复',
  59. 'Turn Into': '换成',
  60. 'Copy Link': '复制链接',
  61. 'Rename': '重命名',
  62. 'Move To': '移动到',
  63. 'Comment': '评论',
  64. 'Color': '颜色',
  65.  
  66. // 设置
  67. // 设置 => 我的账户
  68. 'Me': '我',
  69. 'My Account': '我的账户',
  70. 'Changes to account settings will apply to all of your workspaces.': '帐户设置的更改将应用于您的所有工作区。',
  71. 'Learn more.': '了解更多',
  72. 'Photo': '相片',
  73. 'Upload Photo': '上传相片',
  74. 'Personal Info': '个人信息',
  75. 'Email': '邮箱',
  76. 'Change Email': '更改邮箱',
  77. 'Given Name': '名',
  78. 'Family Name': '姓',
  79. 'Password': '密码',
  80. 'You can set a permanent password if you don\'t want to use temporary login codes.': '如果您不想使用临时登录码,则可以设置永久密码。',
  81. 'Change Password': '更改密码',
  82. 'Remove Password': '移除密码',
  83. 'Calendar Setting': '日历设置',
  84. 'Start week on Monday': '一周从星期一开始',
  85. 'This will change how all calendars in your app look.': '这将会更改您应用中所有日历的外观。',
  86. 'Danger Zone': '危险部分',
  87. 'Delete My Account': '删除我的账户',
  88. 'Update': '更新',
  89. 'Cancel': '取消',
  90. // 设置 => 通知
  91. 'My Notifications': '通知',
  92. 'Learn about mobile and desktop notifications.': '了解有关手机和桌面通知的消息。',
  93. 'Mobile Push Notifications': '向手机推送通知',
  94. 'Receive push notifications on mentions and comments immediately via your mobile apps.': '立即通过您的移动应用接收有关提及和评论的推送通知。',
  95. 'Email Notifications': '邮件通知',
  96. 'Receive email updates on mentions, comments, and edit digests for all the pages you have followed.': '接收有关您关注的所有页面的提及,评论和编辑摘要的电子邮件更新。',
  97. 'My Connected Apps': '已关联的应用',
  98. 'Earn Credit': '赚取积分',
  99. 'Settings': '设置',
  100. 'Members': '成员',
  101. 'Upgrade': '升级',
  102. 'Security & SAML': '安全 & SAML',
  103. 'Dark Mode': '深色模式',
  104. 'Workspace': '工作空间',
  105. 'Name': '名称',
  106. 'You can use your name or the name of your team. Keep it simple.': '您可以使用您的名字或团队的名字,来保持简单化。',
  107. 'Icon': '图标',
  108. 'Upload an image or pick an emoji. It will show up in your sidebar and notifications.': '上传图片或选择表情符号。 它将显示在侧边栏和通知中。',
  109. 'Domain': '域名',
  110. 'Share the link ': '分享这个链接 ',
  111. ' to add anyone with an allowed email domain to your workspace.': ' 来添加任何来自该域下拥有邮箱账号的用户到你的工作空间',
  112. 'Allowed Email Domains': '允许的电子邮箱域',
  113. 'Anyone with email addresses at these domains can automatically join your workspace.': '在这些域中拥有电子邮件地址的任何人都可以自动加入您的工作区。',
  114. 'Export': '导出',
  115. 'Export Entire Workspace': '导出整个工作区',
  116. 'Learn about exporting workspaces.': '了解更多关于导出工作空间',
  117. 'Delete Entire Workspace': '删除整个工作区',
  118. 'Learn about deleting workspaces.': '了解更多关于删除工作区',
  119.  
  120. // 新建页面
  121. 'Open as Page': '作为页面打开',
  122. 'Navigate to this page': '导航到这个页面',
  123. 'Add to': '添加到',
  124. 'Press Enter': '按下 Enter 键',
  125. ' to continue with an empty page': '以空白页继续',
  126. ', or pick a template': ',或者选择一个模板',
  127. ' (↑↓ to select)': ' (↑↓ 键选择)',
  128. 'Empty With Icon': '空白有图标',
  129. 'Empty': '空白',
  130. 'Database': '数据库',
  131.  
  132. 'Small Text': '小文字'
  133. });
  134.  
  135.  
  136.  
  137. const NotionApp = window.document.getElementById('notion-app');
  138.  
  139. function getTextNode(node) {
  140. const sentences = [];
  141.  
  142. const _getTextNode = function(node) {
  143. for (let childNode of node.childNodes) {
  144. if (childNode instanceof window.Text) {
  145. if (childNode.data.replace(/[' ']*/, '')) {
  146. sentences.push(childNode);
  147. }
  148. } else if (childNode.placeholder) {
  149.  
  150. }
  151. _getTextNode(childNode);
  152. }
  153. };
  154. _getTextNode(node);
  155. return sentences;
  156. }
  157.  
  158. function translate(node) {
  159. const sentences = getTextNode(node);
  160. for (let text of sentences) {
  161. const string = text.data;
  162. if (I18n.zh[string]) {
  163. text.parentNode.replaceChild(new window.Text(I18n.zh[string]), text);
  164. }
  165. }
  166. }
  167.  
  168. setTimeout(() => {
  169. window.requestIdleCallback(() => {
  170. translate(NotionApp);
  171.  
  172. const observer = new MutationObserver(function(mutationsList) {
  173. return window.requestIdleCallback(function() {
  174. mutationsList = mutationsList.filter(MutationRecord => {
  175. return MutationRecord.addedNodes.length !== 0;
  176. }).map(MutationRecord => {
  177. return MutationRecord.addedNodes;
  178. });
  179.  
  180. for (let nodeList of mutationsList) {
  181. for (let node of nodeList) {
  182. translate(node);
  183. }
  184. }
  185. });
  186. });
  187.  
  188. observer.observe(NotionApp, {
  189. childList: true,
  190. subtree: true
  191. });
  192. });
  193. });
  194. })();