├── apt-packages.txt
├── .github
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── bug-提交-简体中文-.md
│ └── bug-提交-繁體中文-.md
├── copilot-instructions.md
├── dependabot.yml
└── workflows
│ ├── remove_dup.yml
│ ├── update_contributors_images.yml
│ ├── locals(greasyfork).js_update.yaml
│ └── main.user.js_version_update_and_sync_zh-TW.yaml
├── preview
├── img1.png
├── img2.png
├── img3.png
└── img4.png
├── .gitignore
├── t2s_rules.conf
├── .editorconfig
├── script
├── rd.py
├── t2s-convert.pl
└── ci_commit_with_signature.sh
├── README_zh-TW.md
├── README.md
├── main(greasyfork).user.js
├── main_zh-TW.user.js
├── main.user.js
└── LICENSE
/apt-packages.txt:
--------------------------------------------------------------------------------
1 | opencc
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 |
--------------------------------------------------------------------------------
/.github/copilot-instructions.md:
--------------------------------------------------------------------------------
1 | When performing a code review, respond in Chinese.
2 |
--------------------------------------------------------------------------------
/preview/img1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maboloshi/github-chinese/HEAD/preview/img1.png
--------------------------------------------------------------------------------
/preview/img2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maboloshi/github-chinese/HEAD/preview/img2.png
--------------------------------------------------------------------------------
/preview/img3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maboloshi/github-chinese/HEAD/preview/img3.png
--------------------------------------------------------------------------------
/preview/img4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maboloshi/github-chinese/HEAD/preview/img4.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | !.gitignore
2 |
3 | # windows thumbnail cache
4 | Thumbs.db
5 | Desktop.ini
6 |
7 | # Mac DS_Store Files
8 | .DS_Store
9 |
10 | # webstorm
11 | .idea
12 |
13 | main(local).js
--------------------------------------------------------------------------------
/t2s_rules.conf:
--------------------------------------------------------------------------------
1 | # 格式说明:
2 | # 普通替换:源文本(2+空格)目标文本
3 | # 正则替换:REGEX:模式(2+空格)替换文本
4 | zh-CN zh-TW
5 | 隻讀 只讀
6 | 隻影響 只影響
7 | 隻是 只是
8 | 復刻 複刻
9 | 軟件 軟體
10 | 代碼 程式碼
11 | 程序 程式
12 | 項目 專案
13 | 併合並 並合併
14 | 合並 合併
15 | 復雜 複雜
16 | 提交併 提交並
17 | 髮送 發送
18 | REGEX:(?'
34 | closeDelimiter=''
35 | sed -i "/$openDelimiter/,/$closeDelimiter/c\\$openDelimiter$escapedHtmlList$closeDelimiter" README.md
36 | git diff --quiet --exit-code README.md || echo "CHANGES_DETECTED=true" >> $GITHUB_ENV
37 |
38 | - name: Commit and push README.md
39 | if: ${{ env.CHANGES_DETECTED == 'true' }}
40 | env:
41 | GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
42 | APP_SLUG: ${{ steps.generate_token.outputs.app-slug }}
43 | run: |
44 | bash script/ci_commit_with_signature.sh \
45 | -R "${{ github.repository }}" \
46 | -B "${{ github.ref_name }}" \
47 | -P "${{ github.sha }}" \
48 | -F "README.md" \
49 | -h "修改文档: 更新\`贡献者列表\`"
50 |
--------------------------------------------------------------------------------
/.github/workflows/locals(greasyfork).js_update.yaml:
--------------------------------------------------------------------------------
1 | name: main(greasyfork).user.js and locals(greasyfork).js update
2 | on:
3 | schedule:
4 | # 每周四的UTC时间16点(北京时间周五凌晨0点)
5 | - cron: "0 16 * * 4"
6 | workflow_dispatch:
7 |
8 | permissions:
9 | contents: write
10 |
11 | jobs:
12 | update_version:
13 | runs-on: ubuntu-latest
14 | environment: github-pages
15 | steps:
16 | - name: Generate a token
17 | id: generate_token
18 | uses: actions/create-github-app-token@v2
19 | with:
20 | app-id: ${{ vars.APP_ID }}
21 | private-key: ${{ secrets.APP_PRIVATE_KEY }}
22 |
23 | - name: Checkout repository
24 | uses: actions/checkout@v4
25 | with:
26 | fetch-depth: 0
27 |
28 | - name: Sync update locals(greasyfork).js
29 | run: |
30 | # 获得最近以`main.user.js Update to version`开头的提交的引用
31 | ref=$(git log --grep="^main.user.js Update to" -n 1 --pretty=format:"%H")
32 |
33 | # 获取该提交中`locals.js`的文件时间, 并设置环境变量
34 | locals_js_time=$(git log -1 --format=%at $ref -- locals.js)
35 | echo "locals_js_time=$locals_js_time" >> $GITHUB_ENV
36 |
37 | # 从该提交中提取文件`locals.js`并覆写到本地文件`locals(greasyfork).js`
38 | git show $ref:locals.js > "locals(greasyfork).js"
39 |
40 | git diff --quiet --exit-code "locals(greasyfork).js" || \
41 | echo "LOCALS_JS_CHANGED=true" >> $GITHUB_ENV
42 |
43 | - name: Update version in main(greasyfork).user.js
44 | if: |
45 | ${{ env.LOCALS_JS_CHANGED == 'true' }}
46 | run: |
47 | # 使用`locals.js`的文件日期为词库版本号
48 | locals_js_date=$(TZ='Asia/Shanghai' date -d "@${{ env.locals_js_time }}" +'%Y-%m-%d')
49 | sed -i -E "
50 | s/(@version\s*([0-9]+\.){2}[0-9]+)(-[0-9]{4}-[0-9]{2}-[0-9]{2})?/\1-$locals_js_date/
51 | s/(@require.+435207-github-.+.js\?v([0-9]+\.){2}[0-9]+)(-[0-9]{4}-[0-9]{2}-[0-9]{2})?/\1-$locals_js_date/
52 | " "main(greasyfork).user.js"
53 |
54 | git diff --quiet --exit-code "main(greasyfork).user.js" || \
55 | echo "MAIN_USER_JS_CHANGED=true" >> $GITHUB_ENV
56 |
57 | - name: Commit and push locals(greasyfork).js and main(greasyfork).user.js
58 | if: ${{ env.LOCALS_JS_CHANGED == 'true' &&
59 | env.MAIN_USER_JS_CHANGED == 'true' }}
60 | env:
61 | GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
62 | APP_SLUG: ${{ steps.generate_token.outputs.app-slug }}
63 | run: |
64 | version=$(sed -n -E 's/^\/\/ @version\s+(.+)/\1/p' "main(greasyfork).user.js")
65 | bash script/ci_commit_with_signature.sh \
66 | -R "${{ github.repository }}" \
67 | -B "${{ github.ref_name }}" \
68 | -P "${{ github.sha }}" \
69 | -F "locals(greasyfork).js, main(greasyfork).user.js" \
70 | -h "main(greasyfork).user.js Sync Thesaurus to $version"
71 |
--------------------------------------------------------------------------------
/script/t2s-convert.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | use strict;
3 | use warnings;
4 | use utf8;
5 | use open ':std', ':encoding(UTF-8)';
6 | use Getopt::Long;
7 | use Cwd qw(abs_path);
8 | use File::Copy qw(move);
9 |
10 | # 配置参数
11 | my %opt = (
12 | rules => 't2s_rules.conf', # 默认规则文件
13 | backup => 0, # 是否备份
14 | verbose => 0, # 显示详细信息
15 | encoding => 'UTF-8', # 文件编码
16 | output => undef, # 输出目录或文件
17 |
18 | );
19 | GetOptions(
20 | 'r|rules=s' => \$opt{rules},
21 | 'b|backup' => \$opt{backup},
22 | 'v|verbose' => \$opt{verbose},
23 | 'e|encoding=s' => \$opt{encoding},
24 | 'o|output=s' => \$opt{output},
25 | 'h|help' => sub { usage() },
26 | ) or usage(1);
27 |
28 | # 参数校验
29 | usage(1) unless @ARGV;
30 | -e $opt{rules} or die "[ERROR] 规则文件 '$opt{rules}' 不存在\n";
31 |
32 | # 预加载规则
33 | my @rules;
34 | load_rules($opt{rules}, \@rules);
35 |
36 | # 处理文件
37 | foreach my $file (@ARGV) {
38 | convert_file($file, \@rules);
39 | }
40 |
41 | #=============== 子函数 ================
42 | sub load_rules {
43 | my ($rule_file, $rules_ref) = @_;
44 |
45 | open(my $fh, '<:encoding(UTF-8)', $rule_file)
46 | or die "[ERROR] 无法打开规则文件 '$rule_file': $!\n";
47 |
48 | while (<$fh>) {
49 | chomp;
50 | next if /^\s*#/ || /^\s*$/; # 跳过注释和空行
51 |
52 | # 解析规则行(支持2+空格对齐和REGEX:标记)
53 | my ($is_regex, $pattern, $replacement) = parse_rule_line($_);
54 |
55 | # 编译正则表达式
56 | my $compiled = $is_regex ? qr/$pattern/ : qr/\Q$pattern\E/;
57 | push @$rules_ref, {
58 | pattern => $compiled,
59 | replace => $replacement,
60 | raw => $_
61 | };
62 |
63 | print "[RULE] 已加载: $_\n" if $opt{verbose};
64 | }
65 | close $fh;
66 | }
67 |
68 | sub parse_rule_line {
69 | my ($line) = @_;
70 |
71 | my $is_regex = ($line =~ s/^REGEX://) ? 1 : 0; # 识别正则表达式标记
72 | my ($p, $r) = split(/\s{2,}/, $line, 2); # 提取参数,支持2+空格分隔
73 |
74 | unless (defined $p && defined $r) {
75 | my $type = $is_regex ? '(REGEX)' : '';
76 | die "[ERROR] 规则格式错误$type: '$line'\n";
77 | }
78 |
79 | # 正则语法检测
80 | if ($is_regex) {
81 | eval { qr/$p/ };
82 | if ($@) {
83 | die "[ERROR] 无效的正则表达式 '$p': $@\n";
84 | }
85 | }
86 |
87 | return ($is_regex, $p, $r);
88 | }
89 |
90 | sub convert_file {
91 | my ($file, $rules_ref) = @_;
92 |
93 | # 备份处理
94 | my $bak_file = "$file.bak";
95 | if ($opt{backup} && !-e $bak_file) {
96 | move ($file, $bak_file)
97 | or die "[ERROR] 备份失败: 无法将 '$file' 备份为 '$bak_file': $!\n";
98 | }
99 |
100 | my $input_file = ($opt{backup} && -e $bak_file) ? $bak_file : $file;
101 | open(my $in, '<:encoding('.$opt{encoding}.')', $input_file)
102 | or die "[ERROR] 无法读取文件 '$input_file': $!\n";
103 | open(my $out, '>:encoding('.$opt{encoding}.')', "$file.tmp")
104 | or die "[ERROR] 无法创建临时文件 '$file.tmp': $!\n";
105 |
106 | # 逐行处理
107 | my $count = 0;
108 | while (<$in>) {
109 | my $origin = $_;
110 | foreach my $rule (@$rules_ref) {
111 | s/$rule->{pattern}/$rule->{replace}/g;
112 | }
113 | print $out $_;
114 | $count += 1;
115 | print "已处理 $count 行\r" if $opt{verbose} && $count % 100 == 0;
116 | }
117 |
118 | close $in;
119 | close $out;
120 |
121 | # 文件输出处理
122 | my $out_path;
123 | if (defined $opt{output}) {
124 | if (-d $opt{output}) {
125 | my $basename = $file;
126 | $basename =~ s|.*/||;
127 | $out_path = "$opt{output}/$basename";
128 | } else {
129 | $out_path = $opt{output};
130 | }
131 | } else {
132 | $out_path = $file;
133 | }
134 |
135 | move("$file.tmp", $out_path)
136 | or die "[ERROR] 无法将临时文件 '$file.tmp' 移动为 '$out_path': $!\n";
137 |
138 | unlink $bak_file unless $opt{backup};
139 |
140 | print "\n[OK] 已转换 $file (共 $count 行)\n" if $opt{verbose};
141 | print "[OK] 已输出到 $out_path\n" if $opt{verbose};
142 | }
143 |
144 | sub usage {
145 | print <<"END_USAGE";
146 | 简繁转换脚本 v2.0
147 | 用法: $0 [选项] 文件1 文件2...
148 |
149 | 选项:
150 | -r, --rules=FILE 规则配置文件 (默认: $opt{rules})
151 | -b, --backup 保留原始文件备份 (.bak)
152 | -e, --encoding=ENC 文件编码 (默认: $opt{encoding})
153 | -o, --output=PATH 输出文件路径或目录
154 | -v, --verbose 显示详细处理信息
155 | -h, --help 显示此帮助信息
156 |
157 | 规则文件格式:
158 | 普通替换: 原文本[2+空格]替换文本
159 | 正则替换: REGEX:模式[2+空格]替换文本
160 |
161 | 示例:
162 | $0 -v -b locals_zh-TW.js
163 | $0 -v -o ../locals_zh-TW.js
164 | $0 -r custom_rules.conf *.js
165 | END_USAGE
166 | exit($_[0] || 0);
167 | ;
168 | }
169 |
--------------------------------------------------------------------------------
/script/ci_commit_with_signature.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | while getopts ":T:R:B:P:F:D:h:b:" opt; do
4 | case $opt in
5 | T)
6 | # 通过 GitHub GraphQL API 进行身份验证的 TOKEN
7 | # TOKEN for authentication via the GitHub GraphQL API
8 | TOKEN=$OPTARG
9 | ;;
10 | R)
11 | # GitHub GraphQL API 请求带有所有者的远程仓库名称
12 | # Remote repository name with owner requested by the GitHub GraphQL API
13 | repoNwo=$OPTARG
14 | ;;
15 | B)
16 | # GitHub GraphQL API 请求的远程仓库目标分支名称
17 | # The name of the target branch of the remote repository requested by the GitHub GraphQL API
18 | branch=$OPTARG
19 | ;;
20 | P)
21 | # 远程仓库目标分支上最后一次提交的 SHA。
22 | # 它也是即将创建的提交的父提交的 SHA。
23 | # The SHA of the last commit on the target branch of the remote repository.
24 | # It is also the SHA of the parent commit of the commit about to be created.
25 | parentSHA=$OPTARG
26 | ;;
27 | F)
28 | # 通过 GitHub GraphQL API 提交, 新增或修改的文件的路径(相对于存储库根)的数组
29 | # Array of paths (relative to the repository root) to new or modified files for commits via the GitHub GraphQL API
30 | IFS=', ' read -ra changed_files <<< "${OPTARG:-}"
31 | # 使用逗号和或空格作为分隔符,将参数分割为数组,默认值为空字符串
32 | # Split parameters into arrays using commas and or spaces as separators, defaults to empty string
33 | ;;
34 | D)
35 | # 通过 GitHub GraphQL API 提交, 删除的文件的路径(相对于存储库根)的数组
36 | # Array of paths (relative to the repository root) to deleted files for commits via the GitHub GraphQL API
37 | IFS=', ' read -ra deleted_files <<< "${OPTARG:-}"
38 | ;;
39 | h)
40 | # 通过 GitHub GraphQL API 提交的提交消息标题行
41 | # Commit message head line committed via GitHub GraphQL API
42 | message_headline=$OPTARG
43 | ;;
44 | b)
45 | # 通过 GitHub GraphQL API 提交的提交消息正文
46 | # Commit message body committed via GitHub GraphQL API
47 | message_body=$OPTARG
48 | ;;
49 | \?)
50 | echo "无效的选项: -$OPTARG" >&2
51 | exit 1
52 | ;;
53 | esac
54 | done
55 |
56 | if [[ -z $TOKEN ]]; then
57 | TOKEN=$GITHUB_TOKEN
58 | fi
59 |
60 | if [[ -z $GITHUB_API_URL ]]; then
61 | GITHUB_API_URL="https://api.github.com"
62 | fi
63 |
64 | function set_dco_signature {
65 | if [[ $TOKEN == ghp_* ]]; then
66 | # https://github.blog/2021-04-05-behind-githubs-new-authentication-token-formats/
67 | # 'ghp_'开头的是 GitHub 个人访问令牌
68 | # What starts with 'ghp_' is the GitHub personal access token
69 |
70 | res=$(curl -s -H "Authorization: token $TOKEN" "$GITHUB_API_URL/user" 2>/dev/null || echo '{"login":"gh-actions","id":0}')
71 | else
72 | bot="${APP_SLUG:-github-actions}[bot]"
73 | res=$(curl -sg -H "Authorization: token $TOKEN" "$GITHUB_API_URL/users/${bot}" 2>/dev/null || echo '{"login":"gh-actions","id":0}')
74 | fi
75 |
76 | login=$(jq -r .login <<< "$res")
77 | name=$(jq -r '.name // empty' <<< "$res")
78 | id=$(jq -r .id <<< "$res")
79 | echo "Signed-off-by: ${name:-$login} <$id+$login@users.noreply.github.com>"
80 | }
81 |
82 | message_body="${message_body:+$message_body\n}$(set_dco_signature)"
83 |
84 | # 处理文件修改并构建 fileChanges 部分中 additions 的 JSON 字符串
85 | # Process the file changes and build the JSON string of `additions` in the `fileChanges` section
86 | changed_files_json=""
87 | for file_path in "${changed_files[@]}"; do
88 | changed_files_json+="{
89 | \"path\": \"$file_path\",
90 | \"contents\": \"$(base64 < "$file_path")\"
91 | },
92 | "
93 | done
94 | changed_files_json="${changed_files_json%,
95 | }" # 移除最后一个逗号及换行符和空格
96 | # Remove last comma and line breaks and spaces
97 |
98 | # 处理文件删除并构建 fileChanges 部分中 deletions 的 JSON 字符串
99 | # Process the file deletions and build the JSON string of `deletions` in the `fileChanges` section
100 | deleted_files_json=""
101 | for file_path in "${deleted_files[@]}"; do
102 | deleted_files_json+="{
103 | \"path\": \"$file_path\",
104 | },
105 | "
106 | done
107 | deleted_files_json="${deleted_files_json%,
108 | }" # 移除最后一个逗号及换行符和空格
109 | # Remove last comma and line breaks and spaces
110 |
111 | # 构建 GraphQL 请求的 JSON 字符串
112 | # Construct JSON string for GraphQL request
113 | graphql_request='{
114 | "query": "mutation ($input: CreateCommitOnBranchInput!) {
115 | createCommitOnBranch(input: $input) {
116 | commit {
117 | oid,
118 | url
119 | }
120 | }
121 | }",
122 | "variables": {
123 | "input": {
124 | "branch": {
125 | "repositoryNameWithOwner": "'"$repoNwo"'",
126 | "branchName": "'"$branch"'"
127 | },
128 | "message": {
129 | "headline": "'"$message_headline"'",
130 | "body": "'"$message_body"'"
131 | },
132 | "fileChanges": {
133 | "additions": [
134 | '"$changed_files_json"'
135 | ],
136 | "deletions": [
137 | '"$deleted_files_json"'
138 | ]
139 | },
140 | "expectedHeadOid": "'"$parentSHA"'"
141 | }
142 | }
143 | }'
144 |
145 | # 将请求数据写入 request.json 文件
146 | # Write the request data to the `request.json` file
147 | echo "$graphql_request" > request.json
148 |
149 | # 发送 GraphQL 请求并解析结果
150 | # Send GraphQL requests and parse the results
151 | if [[ -z $GITHUB_GRAPHQL_URL ]]; then
152 | GITHUB_GRAPHQL_URL="https://api.github.com/graphql"
153 | fi
154 |
155 | response=$(curl "$GITHUB_GRAPHQL_URL" --silent \
156 | --write-out '%{stderr}HTTP status: %{response_code}\n\n' \
157 | -H "Authorization: bearer $TOKEN" \
158 | --data @request.json)
159 |
160 | # Print the results
161 | jq -r '
162 | if .data?.createCommitOnBranch?.commit?.url then
163 | "✅ 请求成功,SHA: \(.data.createCommitOnBranch.commit.oid)\nURL: \(.data.createCommitOnBranch.commit.url)"
164 | else
165 | if .errors then
166 | "❌ 错误列表:\n" + ([.errors[].message] | join("\n- "))
167 | else
168 | "⚠️ 未知响应格式: \(.)"
169 | end
170 | end' <<< "$response"
171 |
--------------------------------------------------------------------------------
/.github/workflows/main.user.js_version_update_and_sync_zh-TW.yaml:
--------------------------------------------------------------------------------
1 | name: main.user.js version update & sync zh-TW
2 | on:
3 | schedule:
4 | # 每周日的UTC时间16点(北京时间周一凌晨0点)
5 | - cron: "0 16 * * 0"
6 | workflow_dispatch:
7 |
8 | permissions:
9 | contents: write
10 |
11 | jobs:
12 | update_main:
13 | runs-on: ubuntu-latest
14 | environment: github-pages
15 | outputs:
16 | locals_js_date: ${{ steps.version_update.outputs.locals_js_date }}
17 | oid: ${{ steps.api_commit.outputs.oid }}
18 | steps:
19 | - name: Generate a token
20 | id: generate_token
21 | uses: actions/create-github-app-token@v2
22 | with:
23 | app-id: ${{ vars.APP_ID }}
24 | private-key: ${{ secrets.APP_PRIVATE_KEY }}
25 |
26 | - name: Checkout repository
27 | uses: actions/checkout@v4
28 | with:
29 | fetch-depth: 0
30 |
31 | - name: Test if locals.js has changed since the last release
32 | id: detect_locals_js_changes
33 | run: |
34 | # 最近提交是否存在tag
35 | if [ ! "$(git tag --contains ${{ github.sha }})" ]; then
36 | # 获得最近以`main.user.js Update to`开头的提交的sha和时间戳
37 | release_commit_sha=$(git log --grep="^main.user.js Update to" -n 1 --pretty=format:"%H")
38 | release_commit_timestamp=$(git show -s --format=%ct $release_commit_sha)
39 |
40 | # 最近的tag对应提交的sha和时间戳
41 | latest_tag_commit_sha=$(git rev-list --tags --max-count=1)
42 | latest_tag_commit_timestamp=$(git show -s --format=%ct $latest_tag_commit_sha)
43 |
44 | if [ $release_commit_timestamp -gt $latest_tag_commit_timestamp ]; then
45 | ref=$release_commit_sha
46 | else
47 | ref=$latest_tag_commit_sha
48 | fi
49 |
50 | # 如果 locals.js 变化,设置环境变量
51 | git diff --quiet --exit-code $ref locals.js || \
52 | echo "LOCALS_JS_CHANGED=true" >> $GITHUB_ENV
53 | fi
54 |
55 | # 如果 locals.js 没有变化,直接跳过后续步骤
56 | - name: Exit if no changes in locals.js
57 | if: env.LOCALS_JS_CHANGED != 'true'
58 | run: echo "No changes in locals.js, exiting..."
59 |
60 | - name: Update version in main.user.js
61 | id: version_update
62 | if: env.LOCALS_JS_CHANGED == 'true'
63 | run: |
64 | # 获取最后一次提交中`locals.js`的文件时间
65 | locals_js_time=$(git log -1 --format=%at -- locals.js)
66 |
67 | # 使用`locals.js`的文件日期为词库版本号
68 | locals_js_date=$(TZ='Asia/Shanghai' date -d "@$locals_js_time" +'%Y-%m-%d')
69 | echo "locals_js_date=$locals_js_date" >> $GITHUB_OUTPUT
70 |
71 | # 更新 main.user.js
72 | sed -i -E "
73 | s/(@version\s*([0-9]+\.){2}[0-9]+)(-[0-9]{4}-[0-9]{2}-[0-9]{2})?/\1-$locals_js_date/
74 | s/(@require.+locals\.js\?v([0-9]+\.){2}[0-9]+)(-[0-9]{4}-[0-9]{2}-[0-9]{2})?/\1-$locals_js_date/
75 | " main.user.js
76 |
77 | # 如果 main.user.js 变化,设置环境变量
78 | git diff --quiet --exit-code main.user.js || \
79 | echo "MAIN_USER_JS_CHANGED=true" >> $GITHUB_ENV
80 |
81 | - name: Commit and push main.user.js
82 | id: api_commit
83 | if: env.LOCALS_JS_CHANGED == 'true' && env.MAIN_USER_JS_CHANGED == 'true'
84 | env:
85 | GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
86 | APP_SLUG: ${{ steps.generate_token.outputs.app-slug }}
87 | run: |
88 | version=$(sed -n -E 's/^\/\/ @version\s+(.+)/\1/p' main.user.js)
89 | oid=$(bash script/ci_commit_with_signature.sh \
90 | -R "${{ github.repository }}" \
91 | -B "${{ github.ref_name }}" \
92 | -P "${{ github.sha }}" \
93 | -F "main.user.js" \
94 | -h "main.user.js Update to $version" | tee >(cat >&2) | grep -oP '✅ 请求成功,SHA: \K[a-f0-9]{40}')
95 |
96 | # 验证SHA格式
97 | if [[ "$oid" =~ ^[a-f0-9]{40}$ ]]; then
98 | echo "oid=$oid" >> $GITHUB_OUTPUT
99 | fi
100 |
101 | sync_zh_tw:
102 | runs-on: ubuntu-latest
103 | if: success() && needs.update_main.outputs.oid
104 | needs: update_main
105 | environment: github-pages
106 | steps:
107 | - name: Checkout files
108 | uses: actions/checkout@v4
109 | with:
110 | ref: ${{ needs.update_main.outputs.oid }}
111 |
112 | - name: Generate token
113 | id: generate_token
114 | uses: actions/create-github-app-token@v2
115 | with:
116 | app-id: ${{ vars.APP_ID }}
117 | private-key: ${{ secrets.APP_PRIVATE_KEY }}
118 |
119 | - name: Cache apt packages
120 | uses: actions/cache@v4
121 | with:
122 | path: |
123 | /var/cache/apt/archives/*.deb
124 | !/var/cache/apt/archives/partial
125 | !/var/cache/apt/archives/lock
126 | key: apt-${{ runner.os }}-${{ hashFiles('**/apt-packages.txt') }}
127 | restore-keys: |
128 | apt-${{ runner.os }}-
129 |
130 | - name: Install OpenCC
131 | run: |
132 | sudo apt-get update
133 | sudo apt-get install -y opencc
134 |
135 | - name: Sync locals.js -> locals_zh-TW.js
136 | run: |
137 | opencc -i locals.js -o locals_zh-TW.js -c s2tw.json
138 | perl ./script/t2s-convert.pl -v locals_zh-TW.js
139 |
140 | - name: Update version in main_zh-TW.user.js
141 | run: |
142 | # 同步版本号
143 | locals_js_date="${{ needs.update_main.outputs.locals_js_date }}"
144 | sed -i -E "
145 | s/(@version\s*([0-9]+\.){2}[0-9]+)(-[0-9]{4}-[0-9]{2}-[0-9]{2})?/\1-$locals_js_date/
146 | s/(@require.+locals_zh-TW.js\?v([0-9]+\.){2}[0-9]+)(-[0-9]{4}-[0-9]{2}-[0-9]{2})?/\1-$locals_js_date/
147 | " main_zh-TW.user.js
148 |
149 | - name: Commit and push main_zh-TW.user.js, locals_zh-TW.js
150 | env:
151 | GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
152 | APP_SLUG: ${{ steps.generate_token.outputs.app-slug }}
153 | run: |
154 | version=$(sed -n -E 's/^\/\/ @version\s+(.+)/\1/p' main_zh-TW.user.js)
155 | bash script/ci_commit_with_signature.sh \
156 | -R "${{ github.repository }}" \
157 | -B "${{ github.ref_name }}" \
158 | -P "${{ needs.update_main.outputs.oid }}" \
159 | -F "main_zh-TW.user.js, locals_zh-TW.js" \
160 | -h "main_zh-TW.user.js Sync Thesaurus to $version"
161 |
--------------------------------------------------------------------------------
/README_zh-TW.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # [GitHub 中文化插件][github-project-link]
4 |
5 | > 讓 GitHub 界面全面中文化 | 源自 [52cik/github-hans](https://github.com/52cik/github-hans)
6 |
7 | [简体中文](./README.md) · **繁體中文** · [反饋問題][github-issues-link]
8 |
9 |
10 |
11 | [![GitHub issues][github-issues-shield]][github-issues-link]
12 | [![GitHub stars][github-stars-shield]][github-stars-link]
13 | [![GitHub forks][github-forks-shield]][github-forks-link]
14 | [![license GPL-3.0][github-license-shield]][github-license-link]
15 | [![GreasyFork installs][greasyFork-shield]][greasyFork-link]
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | > [!warning]
28 | > 本項目從未發佈至 GitCode,如您發現請截圖並保留證據
29 |
30 | > [!IMPORTANT]
31 | > 💡 **重要:** 本繁體語言版本,使用基於[OpenCC](https://github.com/BYVoid/OpenCC)及[自定義規則](./t2s_rules.conf)轉換
32 |
33 |
34 | 目錄樹
35 |
36 | #### TOC
37 | - [🌟 功能特性](#-功能特性)
38 | - [🌐 兼容環境](#-兼容環境)
39 | - [💻 安裝指南](#-安裝指南)
40 | - [🔧 本地調試](#-本地調試)
41 | - [🔄 更新日誌](#-更新日誌)
42 | - [📌 待辦事項](#-待辦事項)
43 | - [🤝 參與貢獻](#-參與貢獻)
44 | - [🖼️ 效果預覽](#-效果預覽)
45 | - [🙏 特別鳴謝](#-特別鳴謝)
46 | - [📈 項目統計](#-項目統計)
47 | - [🎁 歡迎打賞](#-歡迎打賞)
48 |
49 |
50 | ## 🌟 功能特性
51 |
52 | - [x] 全面中文化 GitHub 界面元素(菜單欄、標題、按鈕等)
53 | - [x] 智能正則匹配功能
54 | - [x] 支持項目描述的人機翻譯
55 | - [x] 自動本地化時間元素
56 | - [x] 持續更新詞庫
57 |
58 | ## 🌐 兼容環境
59 |
60 | 瀏覽器類型 | 支持的腳本管理器
61 | :------------------: | :---------------:
62 | Chrome / Chromium 內核 | [Tampermonkey][Tampermonkey], [Violentmonkey][Violentmonkey]
63 | Safari(全平臺) | [Macaque][Macaque], [Stay][Stay]
64 | Firefox / Gecko 內核 | [Tampermonkey][Tampermonkey], [Violentmonkey][Violentmonkey]
65 | Via(Android) | 內置管理器
66 |
67 | ## 💻 安裝指南
68 |
69 | 1. 安裝用戶腳本管理器:
70 | - 推薦:[Tampermonkey][Tampermonkey]
71 | 1. **基於 Chrome / Chromium 內核瀏覽器:**
72 | 1. 務必開啟 「擴展程序」 管理中的 **「開發者模式」**[^1]
73 | 1. 務必開啟 「擴展程序」 管理中腳本管理器擴展的 **「允許運行用戶腳本」**
74 | 1. 具體可參考 [Tampermonkey 官方指引](https://www.tampermonkey.net/faq.php#Q209)
75 | 1. 選擇安裝源:
76 | - [GitHub 源【開發版】][main_zh-TW.user.js]
77 | 1. 刷新頁面後,插件即可生效
78 | 1. 必要時,重啟瀏覽器
79 |
80 | [^1]: [Chrome 切換到 Manifest V3後,使用問題](https://github.com/maboloshi/github-chinese/issues/234)
81 |
82 | > [!NOTE]
83 | > **版本說明**:
84 | > - 🚀 開發版:實時更新,每週五自動更新詞庫
85 | > - 🛡️ 穩定版:每週一同步開發版詞庫,更穩定
86 |
87 | ## 🔧 本地調試
88 |
89 | 1. 安裝 [Tampermonkey][Tampermonkey],並啟用 “允許訪問文件網址”。
90 | 1. 下載詞庫文件到本地(如:`D:\github-chinese\locals.js`)
91 | 1. 在腳本管理器中修改引用路徑:
92 | ```js
93 | // 原始路徑
94 | // @require https://raw.githubusercontent.com/...
95 |
96 | // 修改為
97 | // @require file:///D:/github-chinese/locals.js
98 | ```
99 | 1. 刷新頁面生效
100 |
101 | > [!TIP]
102 | > 💡 **溫馨提示:** 您可以將詞庫文件拖拽至瀏覽器地址欄,複製路徑直接使用。
103 |
104 |
105 |
106 | [![][back-to-top]](#readme-top)
107 |
108 |
109 |
110 |
111 | ## 🔄 更新日誌
112 |
113 | ### 最新版本
114 |
115 | #### v1.9.3 (2024-08-18)
116 |
117 | 1. 新增功能:通過設置中文環境,自動本地化時間元素,僅保留`on`開頭的時間正則,並停用時間元素監視
118 | 1. 優化突變翻譯處理:
119 | - 引入`characterDataPage`規則,對特定頁面啟用`篩選字符數據`的變更
120 | - 引入`ignoreMutationSelectorPage`規則,忽略特定突變元素
121 | 1. 合併`reIgnoreClass,reIgnoreItemprop,ignoreId,ignoreTag`為`ignoreSelectorPage`規則,處理全局及特定頁面,忽略特定元素
122 | 1. 引入全局緩存模式,減少重複構建包括不限於基於`page`變化的忽略規則、正則規則數組等
123 | 1. 調整:更新訊飛聽見翻譯引擎v2.0
124 | 1. 優化:梳理、優化腳本
125 | 1. 調整:調整詞庫語言代碼為`zh-CN`, 與環境語言設置一致
126 |
127 | 查看更多歷史版本
128 |
129 | #### v1.9.2 (2024-06-14)
130 |
131 | 1. 適配`www.githubstatus.com`
132 | 1. 適配`skills.github.com`
133 |
134 | #### v1.9.1 (2024-05-23)
135 |
136 | 1. 更新`切換正則功能按鈕`
137 |
138 | #### v1.9.0 (2023-12-09)
139 |
140 | 1. 重新定義版本號規則, 如`1.9.0-2023-12-09`。
141 | - `1.9.0`: 主版本號(由項目所有者更新)
142 | - `2023-12-09`:`詞庫`發佈版本號(由 GitHub Action 自動更新)
143 | 1. 加強: [GitHub 源【開發版】][main.user.js]每週一凌晨自動更新`詞庫`發佈版本號
144 | 1. 加強: [GreasyFork 源【穩定版】][main(greasyfork).user.js]每週五凌晨自動更新`詞庫`發佈版本號, 詞庫內容同上一次[GitHub 源【開發版】][main.user.js]
145 | 1. 加強:在 `README.md` 中自動更新貢獻者頭像
146 | 1. 更新: 忽略規則, 詞條等
147 |
148 | #### v1.8.5 (2023-08-31)
149 |
150 | 1. 優化: `transDesc 函數`代碼
151 | 1. 修復: 重複添加`translate-me`翻譯按鈕
152 | 1. 加強:`watchUpdate 函數`新增節點文本更新的情況
153 | 1. 調整: `transBySelector和transDesc函數`延遲執行時間
154 | 1. 更新: 忽略規則, 詞條等
155 |
156 | #### v1.8.4 (2023-08-08)
157 |
158 | 1. 修復: `Itemprop`過濾規則, 依然使用正則方式
159 | 1. 修復: `tooltipped`樣式提示, 依然使用正則方式
160 |
161 | #### v1.8.3 (2023-08-07)
162 |
163 | 1. 梳理、優化腳本
164 | 1. 更新: 忽略規則, 大量詞條等
165 |
166 | #### v1.8.2 (2023-05-15)
167 |
168 | 1. `greasyfork 託管`源切換到`按頁面精細化詞條模式`
169 | 1. 調整詞庫格式
170 | 1. 功能加強: 優化`元素篩選器`翻譯邏輯
171 | 1. 更新: 忽略規則, 大量詞條等
172 |
173 | #### v1.8.1 (2023-01-22)
174 |
175 | 1. 修復: #8 與 dark reader 擴展發生衝突,導致時間顯示出現問題
176 | 1. `GitHub`源開始切換到`按頁面精細化詞條模式(開發版)`, 詞庫未完全遷移適配
177 | 1. 停止`greasyfork`源詞庫文件的同步更新
178 |
179 | #### v1.8.0 (2023-01-18)
180 |
181 | 1. 刪除: `TURBO-FRAME`框架處理代碼. Github 已調整新動態加載模式, 直接檢測`url`的變化就能獲取對應的`page`信息
182 | 1. 新增: 支持時間元素的`Shadow DOM`翻譯, 並監聽變化
183 | 1. 新增: 啟用並更新`時間元素翻譯`專項正則詞條
184 | 1. 新增: 僅當`page`有效才翻譯頁面
185 | 1. 修復: 原`簡介翻譯`引擎`GitHub中文社區`失效, 改為`訊飛`引擎(測試)
186 | 1. 修復: 追加公共正則重複迭代的問題
187 | 1. 修復: 正則標記變量`RegExp`與構造函數`new RegExp`衝突
188 | 1. 更新: 忽略規則, 詞條等
189 |
190 | 預告, 下次將細化`page`匹配規則, 導致詞庫文件結構大調整, 詞庫文件會適當變大, 頁面正則更精細效率會提升
191 |
192 | #### v1.7.9 (2022-07-17)
193 |
194 | GitHub 的 ajax 載入方式逐步從 [defunkt/jquery-pjax](https://github.com/defunkt/jquery-pjax) 切換到 [hotwired/turbo](turbo.hotwired.dev), 導致已有的動態監測方式逐步失效
195 |
196 | 目前, 通過以下修復:
197 |
198 | 1. 新增 `BODY` 元素新增監視
199 | 1. 解析 `TURBO-FRAME` 框架, 獲取對應的 `page`
200 | 1. 修復 github 新動態加載模式, 導致`翻譯描述`返回值無法插入
201 | 1. 修復 github 新動態加載模式, 導致`chrome`瀏覽器自帶翻譯功能卡死頁面
202 |
203 | 其他更新:
204 |
205 | 1. 修復`rePagePath`,`rePagePathRepo`,`rePagePathOrg`匹配規則,限制路徑匹配層次,排除干擾
206 | 1. 直接使用網頁URL`document.URL`變化觸發`標題翻譯`和`JS 篩選器`翻譯
207 | 1. 修復`關閉正則`無法生效, 需要刷新頁面才生效
208 | 1. 日常更新詞庫和忽略規則
209 | 1. 更新`JS 篩選器`規則
210 |
211 | #### v1.7.8 (2022-06-29)
212 |
213 | 1. 緊急修復: GitHub 變更了`document.body`和`title`更新機制, 導致原有的`監測更新`規則部分失效, 目前使用`document.documentElement`監視整個頁面 DOM 的變更
214 | 1. 跳過``標籤
215 | 1. `標題翻譯`和`JS 篩選器`翻譯, 依據 URL變化更新
216 |
217 | #### v1.7.7 (2022-06-26)
218 |
219 | 1. 新增`時間元素翻譯`功能
220 | 1. 重寫`頁面標題翻譯`函數
221 | 1. 梳理`遍歷節點`函數邏輯
222 | 1. 優化`transPage`函數,默認翻譯公共部分
223 | 1. 調整`getPage`函數, 使`ClassName匹配規則`優先
224 | 1. 優化`translate`函數, 跳過`不存在英文字母和符號,.`, 保留首尾空白部分等
225 | 1. 部分函數重命名,使用`es6`新語法
226 | 1. 日常更新詞庫和忽略規則,修復一個`JS 選擇器規則`
227 |
228 | #### v1.7.6 (2022-05-12)
229 |
230 | 1. 日常更新詞庫和忽略規則
231 | 1. 添加手動開啟/禁用正則翻譯,添加切換菜單
232 | 1. 優化翻譯文本函數:避免已翻譯詞彙二次匹配,提高效率;局部翻譯優先於全局
233 |
234 |
235 |
236 |
237 |
238 | [![][back-to-top]](#readme-top)
239 |
240 |
241 |
242 |
243 | ## 📌 待辦事項
244 |
245 | 1. 添加 GitHub 專用名詞解釋
246 | 1. 整理 [Git](https://git-scm.com/) & [GitHub](https://github.com/) 學習資料
247 | 1. 完善文檔翻譯,需大家 PR 共同翻譯
248 |
249 | ## 🤝 參與貢獻
250 |
251 | 歡迎通過以下方式參與貢獻:
252 |
253 | 1. 完善詞庫翻譯(編輯 `locals.js`)
254 | 1. 提交議題報告,參與話題討論
255 | 1. 改進代碼邏輯
256 |
257 | [![][pr-welcome-shield]][pr-welcome-link]
258 |
259 | ### 翻譯參考資源:
260 |
261 | 1. [Pro Git 第二版 簡體中文](https://git-scm.com/book/zh/v2)
262 | 1. [Pro Git: 翻譯約定](https://github.com/progit/progit2-zh/blob/master/TRANSLATION_NOTES.asc)
263 | 1. [Git 官方軟件包的簡體中文翻譯](https://github.com/git/git/blob/master/po/zh_CN.po)
264 | 1. [GitHub 詞彙表官方譯本](https://docs.github.com/cn/get-started/quickstart/github-glossary)
265 | 1. **[CSS 選擇器](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Reference/Selectors) 用於編寫忽略規則**
266 |
267 | > [查看詳細貢獻指南](https://github.com/maboloshi/github-chinese/discussions/57)
268 |
269 | ## 🖼️ 效果預覽
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 | ## 🙏 特別鳴謝
283 |
284 | ### 核心團隊
285 |
286 | - [maboloshi](https://github.com/maboloshi) - 項目作者
287 | - [wyc-26](https://github.com/wyc-26),[陳生雜物房](https://github.com/TC999) - 項目協作者
288 | - [52cik](https://github.com/52cik) - 項目原作者
289 |
290 | ### 貢獻者牆
291 |
292 | 一如既往,感謝我們出色的貢獻者❤️!
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 | > 貢獻者列表,由 [GitHub Action][update-contributors-images] 自動生成
361 |
362 |
363 |
364 | [![][back-to-top]](#readme-top)
365 |
366 |
367 |
368 |
369 | ## 📈 項目統計
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 | 
380 |
381 |
382 |
383 | [![][back-to-top]](#readme-top)
384 |
385 |
386 |
387 | ## 🎁 歡迎打賞
388 | [讚賞列表](https://github.com/maboloshi/maboloshi/issues/1)
389 | | 微信讚賞 | 支付寶讚賞 |
390 | | :--------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: |
391 | |
☕喝點咖啡繼續幹☕ |
🌶️來包辣條吧~🍪 |
392 |
393 |
394 |
395 |
396 | [back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square
397 | [github-project-link]: https://github.com/maboloshi/github-chinese "GitHub 中文化插件"
398 | [github-issues-link]: https://github.com/maboloshi/github-chinese/issues "議題"
399 | [github-issues-shield]: https://img.shields.io/github/issues/maboloshi/github-chinese?style=flat-square&logo=github&label=Issue
400 | [github-stars-link]: https://github.com/maboloshi/github-chinese/stargazers "星標"
401 | [github-stars-shield]: https://img.shields.io/github/stars/maboloshi/github-chinese?style=flat-square&logo=github&label=Star
402 | [github-forks-link]: https://github.com/maboloshi/github-chinese/network "復刻"
403 | [github-forks-shield]: https://img.shields.io/github/forks/maboloshi/github-chinese?style=flat-square&logo=github&label=Fork
404 | [github-license-link]: https://opensource.org/licenses/GPL-3.0 "許可證"
405 | [github-license-shield]: https://img.shields.io/github/license/maboloshi/github-chinese?style=flat-square&logo=github&label=License
406 | [greasyFork-link]: https://greasyfork.org/scripts/435208 "GreasyFork 源 - GitHub 中文化插件"
407 | [greasyFork-shield]: https://img.shields.io/badge/dynamic/json?style=flat-square&logo=GreasyFork&label=GreasyFork&query=total_installs&suffix=%20installs&url=https://greasyfork.org/scripts/435208.json
408 | [pr-welcome-link]: https://github.com/maboloshi/github-chinese/pulls
409 | [pr-welcome-shield]: https://img.shields.io/badge/🤯_pr_welcome-%E2%86%92-ffcb47?labelColor=black&style=for-the-badge "歡迎提交 PR"
410 | [Tampermonkey]: http://tampermonkey.net/ "篡改猴"
411 | [Violentmonkey]: https://violentmonkey.github.io/ "暴力猴"
412 | [Macaque]: https://macaque.app/ "獼猴"
413 | [Stay]: https://apps.apple.com/cn/app/stay-for-safari-%E6%B5%8F%E8%A7%88%E5%99%A8%E4%BC%B4%E4%BE%A3/id1591620171 "Stay"
414 | [main_zh-TW.user.js]: https://github.com/maboloshi/github-chinese/raw/gh-pages/main_zh-TW.user.js "GitHub 中文化插件(繁體版) - GitHub 託管"
415 | [update-contributors-images]: https://github.com/maboloshi/github-chinese/blob/gh-pages/.github/workflows/update_contributors_images.yml
416 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # [GitHub 中文化插件][github-project-link]
4 |
5 | > 让 GitHub 界面全面中文化 | 源自 [52cik/github-hans](https://github.com/52cik/github-hans)
6 |
7 | **简体中文** · [繁體中文](./README_zh-TW.md) · [反馈问题][github-issues-link]
8 |
9 |
10 |
11 | [![GitHub stars][github-stars-shield]][github-stars-link]
12 | [![GitHub forks][github-forks-shield]][github-forks-link]
13 | [![GitHub issues][github-issues-shield]][github-issues-link]
14 | [![license GPL-3.0][github-license-shield]][github-license-link]
15 | [![GreasyFork installs][greasyFork-shield]][greasyFork-link]
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | > [!warning]
28 | > 本项目从未发布至 GitCode,如您发现请截图并保留证据
29 |
30 |
31 | 目录树
32 |
33 | #### TOC
34 | - [🌟 功能特性](#-功能特性)
35 | - [🌐 兼容环境](#-兼容环境)
36 | - [💻 安装指南](#-安装指南)
37 | - [🔧 本地调试](#-本地调试)
38 | - [🔄 更新日志](#-更新日志)
39 | - [📌 待办事项](#-待办事项)
40 | - [🤝 参与贡献](#-参与贡献)
41 | - [🖼️ 效果预览](#-效果预览)
42 | - [🙏 特别鸣谢](#-特别鸣谢)
43 | - [📈 项目统计](#-项目统计)
44 | - [🎁 欢迎打赏](#-欢迎打赏)
45 |
46 |
47 | ## 🌟 功能特性
48 |
49 | - [x] 全面中文化 GitHub 界面元素(菜单栏、标题、按钮等)
50 | - [x] 智能正则匹配功能
51 | - [x] 支持项目描述的人机翻译
52 | - [x] 自动本地化时间元素
53 | - [x] 持续更新词库
54 |
55 | ## 🌐 兼容环境
56 |
57 | 浏览器类型 | 支持的脚本管理器
58 | :------------------: | :---------------:
59 | Chrome / Chromium 内核 | [Tampermonkey][Tampermonkey], [Violentmonkey][Violentmonkey]
60 | Safari(全平台) | [Tampermonkey][Tampermonkey], [Macaque][Macaque], [Stay][Stay]
61 | Firefox / Gecko 内核 | [Tampermonkey][Tampermonkey], [Violentmonkey][Violentmonkey]
62 | Via(Android) | 内置管理器
63 |
64 | ## 💻 安装指南
65 |
66 | 1. 安装用户脚本管理器:
67 | - 推荐:[Tampermonkey][Tampermonkey]
68 | 1. **基于 Chrome / Chromium 内核浏览器:**
69 | 1. 务必开启 “扩展程序” 管理中的 **“开发者模式”**[^1]
70 | 1. 务必开启 “扩展程序” 管理中脚本管理器扩展的 **“允许运行用户脚本”**
71 | 1. 具体可参考 [Tampermonkey 官方指引](https://www.tampermonkey.net/faq.php#Q209)
72 | 1. 选择安装源:
73 | - [GitHub 源【开发版】][main.user.js]
74 | - [GreasyFork 源【稳定版】][main(greasyfork).user.js]
75 | 1. 刷新页面后,插件即可生效
76 | 1. 必要时,重启浏览器
77 |
78 | [^1]: [Chrome 切换到 Manifest V3后,使用问题](https://github.com/maboloshi/github-chinese/issues/234)
79 |
80 | > [!NOTE]
81 | > **版本说明**:
82 | > - 🚀 开发版:实时更新,每周五自动更新词库
83 | > - 🛡️ 稳定版:每周一同步开发版词库,更稳定
84 |
85 | ## 🔧 本地调试
86 |
87 | 1. 安装 [Tampermonkey][Tampermonkey],并启用 “允许访问文件网址”。
88 | 1. 下载词库文件到本地(如:`D:\github-chinese\locals.js`)
89 | 1. 在脚本管理器中修改引用路径:
90 | ```js
91 | // 原始路径
92 | // @require https://raw.githubusercontent.com/...
93 |
94 | // 修改为
95 | // @require file:///D:/github-chinese/locals.js
96 | ```
97 | 1. 刷新页面生效
98 |
99 | > [!IMPORTANT]
100 | > **若无效:**
101 | > 1. 进入 [Tampermonkey][Tampermonkey] 插件`设置页`
102 | > 1. 将 `通用 - 配置模式` 设置为`高级`,进入高级设置模式
103 | > 1. 找到 `安全 - 允许脚本访问本地文件` 并设置为 `外部(@require 和 @resource)`
104 |
105 | > [!TIP]
106 | > 💡 **温馨提示:** 您可以将词库文件拖拽至浏览器地址栏,复制路径直接使用。
107 |
108 |
109 |
110 | [![][back-to-top]](#readme-top)
111 |
112 |
113 |
114 |
115 | ## 🔄 更新日志
116 |
117 | ### 最新版本
118 |
119 | #### v1.9.3 (2024-08-18)
120 |
121 | 1. 新增功能:通过设置中文环境,自动本地化时间元素,仅保留`on`开头的时间正则,并停用时间元素监视
122 | 1. 优化突变翻译处理:
123 | - 引入`characterDataPage`规则,对特定页面启用`筛选字符数据`的变更
124 | - 引入`ignoreMutationSelectorPage`规则,忽略特定突变元素
125 | 1. 合并`reIgnoreClass,reIgnoreItemprop,ignoreId,ignoreTag`为`ignoreSelectorPage`规则,处理全局及特定页面,忽略特定元素
126 | 1. 引入全局缓存模式,减少重复构建包括不限于基于`page`变化的忽略规则、正则规则数组等
127 | 1. 调整:更新讯飞听见翻译引擎v2.0
128 | 1. 优化:梳理、优化脚本
129 | 1. 调整:调整词库语言代码为`zh-CN`, 与环境语言设置一致
130 |
131 | 查看更多历史版本
132 |
133 | #### v1.9.2 (2024-06-14)
134 |
135 | 1. 适配`www.githubstatus.com`
136 | 1. 适配`skills.github.com`
137 |
138 | #### v1.9.1 (2024-05-23)
139 |
140 | 1. 更新`切换正则功能按钮`
141 |
142 | #### v1.9.0 (2023-12-09)
143 |
144 | 1. 重新定义版本号规则, 如`1.9.0-2023-12-09`。
145 | - `1.9.0`: 主版本号(由项目所有者更新)
146 | - `2023-12-09`:`词库`发布版本号(由 GitHub Action 自动更新)
147 | 1. 加强: [GitHub 源【开发版】][main.user.js]每周一凌晨自动更新`词库`发布版本号
148 | 1. 加强: [GreasyFork 源【稳定版】][main(greasyfork).user.js]每周五凌晨自动更新`词库`发布版本号, 词库内容同上一次[GitHub 源【开发版】][main.user.js]
149 | 1. 加强:在 `README.md` 中自动更新贡献者头像
150 | 1. 更新: 忽略规则, 词条等
151 |
152 | #### v1.8.5 (2023-08-31)
153 |
154 | 1. 优化: `transDesc 函数`代码
155 | 1. 修复: 重复添加`translate-me`翻译按钮
156 | 1. 加强:`watchUpdate 函数`新增节点文本更新的情况
157 | 1. 调整: `transBySelector和transDesc函数`延迟执行时间
158 | 1. 更新: 忽略规则, 词条等
159 |
160 | #### v1.8.4 (2023-08-08)
161 |
162 | 1. 修复: `Itemprop`过滤规则, 依然使用正则方式
163 | 1. 修复: `tooltipped`样式提示, 依然使用正则方式
164 |
165 | #### v1.8.3 (2023-08-07)
166 |
167 | 1. 梳理、优化脚本
168 | 1. 更新: 忽略规则, 大量词条等
169 |
170 | #### v1.8.2 (2023-05-15)
171 |
172 | 1. `greasyfork 托管`源切换到`按页面精细化词条模式`
173 | 1. 调整词库格式
174 | 1. 功能加强: 优化`元素筛选器`翻译逻辑
175 | 1. 更新: 忽略规则, 大量词条等
176 |
177 | #### v1.8.1 (2023-01-22)
178 |
179 | 1. 修复: #8 与 dark reader 扩展发生冲突,导致时间显示出现问题
180 | 1. `GitHub`源开始切换到`按页面精细化词条模式(开发版)`, 词库未完全迁移适配
181 | 1. 停止`greasyfork`源词库文件的同步更新
182 |
183 | #### v1.8.0 (2023-01-18)
184 |
185 | 1. 删除: `TURBO-FRAME`框架处理代码. Github 已调整新动态加载模式, 直接检测`url`的变化就能获取对应的`page`信息
186 | 1. 新增: 支持时间元素的`Shadow DOM`翻译, 并监听变化
187 | 1. 新增: 启用并更新`时间元素翻译`专项正则词条
188 | 1. 新增: 仅当`page`有效才翻译页面
189 | 1. 修复: 原`简介翻译`引擎`GitHub中文社区`失效, 改为`讯飞`引擎(测试)
190 | 1. 修复: 追加公共正则重复迭代的问题
191 | 1. 修复: 正则标记变量`RegExp`与构造函数`new RegExp`冲突
192 | 1. 更新: 忽略规则, 词条等
193 |
194 | 预告, 下次将细化`page`匹配规则, 导致词库文件结构大调整, 词库文件会适当变大, 页面正则更精细效率会提升
195 |
196 | #### v1.7.9 (2022-07-17)
197 |
198 | GitHub 的 ajax 载入方式逐步从 [defunkt/jquery-pjax](https://github.com/defunkt/jquery-pjax) 切换到 [hotwired/turbo](turbo.hotwired.dev), 导致已有的动态监测方式逐步失效
199 |
200 | 目前, 通过以下修复:
201 |
202 | 1. 新增 `BODY` 元素新增监视
203 | 1. 解析 `TURBO-FRAME` 框架, 获取对应的 `page`
204 | 1. 修复 github 新动态加载模式, 导致`翻译描述`返回值无法插入
205 | 1. 修复 github 新动态加载模式, 导致`chrome`浏览器自带翻译功能卡死页面
206 |
207 | 其他更新:
208 |
209 | 1. 修复`rePagePath`,`rePagePathRepo`,`rePagePathOrg`匹配规则,限制路径匹配层次,排除干扰
210 | 1. 直接使用网页URL`document.URL`变化触发`标题翻译`和`JS 筛选器`翻译
211 | 1. 修复`关闭正则`无法生效, 需要刷新页面才生效
212 | 1. 日常更新词库和忽略规则
213 | 1. 更新`JS 筛选器`规则
214 |
215 | #### v1.7.8 (2022-06-29)
216 |
217 | 1. 紧急修复: GitHub 变更了`document.body`和`title`更新机制, 导致原有的`监测更新`规则部分失效, 目前使用`document.documentElement`监视整个页面 DOM 的变更
218 | 1. 跳过``标签
219 | 1. `标题翻译`和`JS 筛选器`翻译, 依据 URL变化更新
220 |
221 | #### v1.7.7 (2022-06-26)
222 |
223 | 1. 新增`时间元素翻译`功能
224 | 1. 重写`页面标题翻译`函数
225 | 1. 梳理`遍历节点`函数逻辑
226 | 1. 优化`transPage`函数,默认翻译公共部分
227 | 1. 调整`getPage`函数, 使`ClassName匹配规则`优先
228 | 1. 优化`translate`函数, 跳过`不存在英文字母和符号,.`, 保留首尾空白部分等
229 | 1. 部分函数重命名,使用`es6`新语法
230 | 1. 日常更新词库和忽略规则,修复一个`JS 选择器规则`
231 |
232 | #### v1.7.6 (2022-05-12)
233 |
234 | 1. 日常更新词库和忽略规则
235 | 1. 添加手动开启/禁用正则翻译,添加切换菜单
236 | 1. 优化翻译文本函数:避免已翻译词汇二次匹配,提高效率;局部翻译优先于全局
237 |
238 |
239 |
240 |
241 |
242 | [![][back-to-top]](#readme-top)
243 |
244 |
245 |
246 |
247 | ## 📌 待办事项
248 |
249 | 1. 添加 GitHub 专用名词解释
250 | 1. 整理 [Git](https://git-scm.com/) & [GitHub](https://github.com/) 学习资料
251 | 1. 完善文档翻译,需大家 PR 共同翻译
252 |
253 | ## 🤝 参与贡献
254 |
255 | 欢迎通过以下方式参与贡献:
256 |
257 | 1. 完善词库翻译(编辑 `locals.js`)
258 | 1. 提交议题报告,参与话题讨论
259 | 1. 改进代码逻辑
260 |
261 | [![][pr-welcome-shield]][pr-welcome-link]
262 |
263 | ### 翻译参考资源:
264 |
265 | 1. [Pro Git 第二版 简体中文](https://git-scm.com/book/zh/v2)
266 | 1. [Pro Git: 翻译约定](https://github.com/progit/progit2-zh/blob/master/TRANSLATION_NOTES.asc)
267 | 1. [Git 官方软件包的简体中文翻译](https://github.com/git/git/blob/master/po/zh_CN.po)
268 | 1. [GitHub 词汇表官方译本](https://docs.github.com/cn/get-started/quickstart/github-glossary)
269 | 1. **[CSS 选择器](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Reference/Selectors) 用于编写忽略规则**
270 |
271 | > [查看详细贡献指南](https://github.com/maboloshi/github-chinese/discussions/57)
272 |
273 | ## 🖼️ 效果预览
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 | ## 🙏 特别鸣谢
287 |
288 | ### 核心团队
289 |
290 | - [maboloshi](https://github.com/maboloshi) - 项目作者
291 | - [wyc-26](https://github.com/wyc-26),[陈生杂物房](https://github.com/TC999) - 项目协作者
292 | - [52cik](https://github.com/52cik) - 项目原作者
293 |
294 | ### 贡献者墙
295 |
296 | 一如既往,感谢我们出色的贡献者❤️!
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 | > 贡献者列表,由 [GitHub Action][update-contributors-images] 自动生成
380 |
381 |
382 |
383 | [![][back-to-top]](#readme-top)
384 |
385 |
386 |
387 |
388 | ## 📈 项目统计
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 | 
399 |
400 |
401 |
402 | [![][back-to-top]](#readme-top)
403 |
404 |
405 |
406 | ## 🎁 欢迎打赏
407 | [赞赏列表](https://github.com/maboloshi/maboloshi/issues/1)
408 | | 微信赞赏 | 支付宝赞赏 |
409 | | :--------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------: |
410 | |
☕喝点咖啡继续干☕ |
🌶️来包辣条吧~🍪 |
411 |
412 |
413 |
414 |
415 | [back-to-top]: https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square
416 | [github-project-link]: https://github.com/maboloshi/github-chinese "GitHub 中文化插件"
417 | [github-issues-link]: https://github.com/maboloshi/github-chinese/issues "议题"
418 | [github-issues-shield]: https://img.shields.io/github/issues/maboloshi/github-chinese?style=flat-square&logo=github&label=Issue
419 | [github-stars-link]: https://github.com/maboloshi/github-chinese/stargazers "星标"
420 | [github-stars-shield]: https://img.shields.io/github/stars/maboloshi/github-chinese?style=flat-square&logo=github&label=Star
421 | [github-forks-link]: https://github.com/maboloshi/github-chinese/network "复刻"
422 | [github-forks-shield]: https://img.shields.io/github/forks/maboloshi/github-chinese?style=flat-square&logo=github&label=Fork
423 | [github-license-link]: https://opensource.org/licenses/GPL-3.0 "许可证"
424 | [github-license-shield]: https://img.shields.io/github/license/maboloshi/github-chinese?style=flat-square&logo=github&label=License
425 | [greasyFork-link]: https://greasyfork.org/scripts/435208 "GreasyFork 源 - GitHub 中文化插件"
426 | [greasyFork-shield]: https://img.shields.io/greasyfork/dt/435208?style=flat-square&logo=GreasyFork&label=GreasyFork%20Installs
427 | [pr-welcome-link]: https://github.com/maboloshi/github-chinese/pulls
428 | [pr-welcome-shield]: https://img.shields.io/badge/🤯_pr_welcome-%E2%86%92-ffcb47?labelColor=black&style=for-the-badge "欢迎提交 PR"
429 | [Tampermonkey]: http://tampermonkey.net/ "篡改猴"
430 | [Violentmonkey]: https://violentmonkey.github.io/ "暴力猴"
431 | [Macaque]: https://macaque.app/ "猕猴"
432 | [Stay]: https://apps.apple.com/cn/app/stay-for-safari-%E6%B5%8F%E8%A7%88%E5%99%A8%E4%BC%B4%E4%BE%A3/id1591620171 "Stay"
433 | [main.user.js]: https://github.com/maboloshi/github-chinese/raw/gh-pages/main.user.js "GitHub 中文化插件 - GitHub 源"
434 | [main(greasyfork).user.js]: https://greasyfork.org/scripts/435208-github-%E4%B8%AD%E6%96%87%E5%8C%96%E6%8F%92%E4%BB%B6/code/GitHub%20%E4%B8%AD%E6%96%87%E5%8C%96%E6%8F%92%E4%BB%B6.user.js "GitHub 中文化插件 - GreasyFork 源"
435 | [update-contributors-images]: https://github.com/maboloshi/github-chinese/blob/gh-pages/.github/workflows/update_contributors_images.yml
436 |
--------------------------------------------------------------------------------
/main(greasyfork).user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name GitHub 中文化插件
3 | // @namespace https://github.com/maboloshi/github-chinese
4 | // @description 中文化 GitHub 界面的部分菜单及内容。原作者为楼教主(http://www.52cik.com/)。
5 | // @copyright 2021, 沙漠之子 (https://maboloshi.github.io/Blog)
6 | // @icon https://github.githubassets.com/pinned-octocat.svg
7 | // @version 1.9.2-2025-12-10
8 | // @author 沙漠之子
9 | // @license GPL-3.0
10 | // @match https://github.com/*
11 | // @match https://skills.github.com/*
12 | // @match https://gist.github.com/*
13 | // @match https://www.githubstatus.com/*
14 | // @require https://greasyfork.org/scripts/435207-github-%E4%B8%AD%E6%96%87%E5%8C%96%E6%8F%92%E4%BB%B6-%E4%B8%AD%E6%96%87%E8%AF%8D%E5%BA%93%E8%A7%84%E5%88%99/code/GitHub%20%E4%B8%AD%E6%96%87%E5%8C%96%E6%8F%92%E4%BB%B6%20-%20%E4%B8%AD%E6%96%87%E8%AF%8D%E5%BA%93%E8%A7%84%E5%88%99.js?v1.9.2-2025-12-10
15 | // @run-at document-end
16 | // @grant GM_xmlhttpRequest
17 | // @grant GM_getValue
18 | // @grant GM_setValue
19 | // @grant GM_registerMenuCommand
20 | // @grant GM_unregisterMenuCommand
21 | // @grant GM_notification
22 | // @connect www.iflyrec.com
23 | // @supportURL https://github.com/maboloshi/github-chinese/issues
24 | // ==/UserScript==
25 |
26 | (function (window, document, undefined) {
27 | 'use strict';
28 |
29 | const lang = I18N.zh ? 'zh' : 'zh-CN'; // 设置默认语言
30 | let page;
31 | let enable_RegExp = GM_getValue("enable_RegExp", 1);
32 |
33 | /**
34 | * watchUpdate 函数:监视页面变化,根据变化的节点进行翻译
35 | */
36 | function watchUpdate() {
37 | // 检测浏览器是否支持 MutationObserver
38 | const MutationObserver =
39 | window.MutationObserver ||
40 | window.WebKitMutationObserver ||
41 | window.MozMutationObserver;
42 |
43 | // 获取当前页面的 URL
44 | const getCurrentURL = () => location.href;
45 | getCurrentURL.previousURL = getCurrentURL();
46 |
47 | // 创建 MutationObserver 实例,监听 DOM 变化
48 | const observer = new MutationObserver((mutations, observer) => {
49 | const currentURL = getCurrentURL();
50 |
51 | // 如果页面的 URL 发生变化
52 | if (currentURL !== getCurrentURL.previousURL) {
53 | getCurrentURL.previousURL = currentURL;
54 | page = getPage(); // 当页面地址发生变化时,更新全局变量 page
55 | console.log(`链接变化 page= ${page}`);
56 |
57 | transTitle(); // 翻译页面标题
58 |
59 | if (page) {
60 | setTimeout(() => {
61 | // 使用 CSS 选择器找到页面上的元素,并将其文本内容替换为预定义的翻译
62 | transBySelector();
63 | if (page === "repository") { //仓库简介翻译
64 | transDesc(".f4.my-3");
65 | } else if (page === "gist") { // Gist 简介翻译
66 | transDesc(".gist-content [itemprop='about']");
67 | }
68 | }, 500);
69 | }
70 | }
71 |
72 | if (page) {
73 | // 使用 filter 方法对 mutations 数组进行筛选,
74 | // 返回 `节点增加、文本更新 或 属性更改的 mutation` 组成的新数组 filteredMutations。
75 | const filteredMutations = mutations.filter(mutation => mutation.addedNodes.length > 0 || mutation.type === 'attributes' || mutation.type === 'characterData');
76 |
77 | // 处理每个变化
78 | filteredMutations.forEach(mutation => traverseNode(mutation.target));
79 | }
80 | });
81 |
82 | // 配置 MutationObserver
83 | const config = {
84 | characterData: true,
85 | subtree: true,
86 | childList: true,
87 | attributeFilter: ['value', 'placeholder', 'aria-label', 'data-confirm'], // 仅观察特定属性变化
88 | };
89 |
90 | // 开始观察 document.body 的变化
91 | observer.observe(document.body, config);
92 | }
93 |
94 | /**
95 | * traverseNode 函数:遍历指定的节点,并对节点进行翻译。
96 | * @param {Node} node - 需要遍历的节点。
97 | */
98 | function traverseNode(node) {
99 | // 跳过忽略
100 | if (I18N.conf.reIgnoreId.test(node.id) ||
101 | I18N.conf.reIgnoreClass.test(node.className) ||
102 | I18N.conf.reIgnoreTag.includes(node.tagName) ||
103 | (node.getAttribute && I18N.conf.reIgnoreItemprop.test(node.getAttribute("itemprop")))
104 | ) {
105 | return;
106 | }
107 |
108 | if (node.nodeType === Node.ELEMENT_NODE) { // 元素节点处理
109 |
110 | // 翻译时间元素
111 | if (
112 | ["RELATIVE-TIME", "TIME-AGO", "TIME", "LOCAL-TIME"].includes(node.tagName)
113 | ) {
114 | if (node.shadowRoot) {
115 | transTimeElement(node.shadowRoot);
116 | watchTimeElement(node.shadowRoot);
117 | } else {
118 | transTimeElement(node);
119 | }
120 | return;
121 | }
122 |
123 | // 元素节点属性翻译
124 | if (["INPUT", "TEXTAREA"].includes(node.tagName)) { // 输入框 按钮 文本域
125 | if (["button", "submit", "reset"].includes(node.type)) {
126 | if (node.hasAttribute('data-confirm')) { // 翻译 浏览器 提示对话框
127 | transElement(node, 'data-confirm', true);
128 | }
129 | transElement(node, 'value');
130 | } else {
131 | transElement(node, 'placeholder');
132 | }
133 | } else if (node.tagName === 'BUTTON') {
134 | if (node.hasAttribute('aria-label') && /tooltipped/.test(node.className)) {
135 | transElement(node, 'aria-label', true); // 翻译 浏览器 提示对话框
136 | }
137 | if (node.hasAttribute('title')) {
138 | transElement(node, 'title', true); // 翻译 浏览器 提示对话框
139 | }
140 | if (node.hasAttribute('data-confirm')) {
141 | transElement(node, 'data-confirm', true); // 翻译 浏览器 提示对话框 ok
142 | }
143 | if (node.hasAttribute('data-confirm-text')) {
144 | transElement(node, 'data-confirm-text', true); // 翻译 浏览器 提示对话框 ok
145 | }
146 | if (node.hasAttribute('data-confirm-cancel-text')) {
147 | transElement(node, 'data-confirm-cancel-text', true); // 取消按钮 提醒
148 | }
149 | if (node.hasAttribute('cancel-confirm-text')) {
150 | transElement(node, 'cancel-confirm-text', true); // 取消按钮 提醒
151 | }
152 | if (node.hasAttribute('data-disable-with')) { // 按钮等待提示
153 | transElement(node, 'data-disable-with', true);
154 | }
155 | } else if (node.tagName === 'OPTGROUP') { // 翻译