This is an automated email from the ASF dual-hosted git repository.
xingyue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-seata-go.git
The following commit(s) were added to refs/heads/master by this push:
new d70e3cb8 fix: issue translate robot (#1102)
d70e3cb8 is described below
commit d70e3cb8abb23255f3e59e071e61983ef0504ec8
Author: ThunGuo <[email protected]>
AuthorDate: Mon Apr 6 19:29:59 2026 +0800
fix: issue translate robot (#1102)
* fix: issue translate robot
* fix: issue translate robot
---
.github/workflows/issue-robot.yml | 111 ++++++++++++++++++++++++++++++++++++--
1 file changed, 106 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/issue-robot.yml
b/.github/workflows/issue-robot.yml
index 3052ce99..bbdfb62d 100644
--- a/.github/workflows/issue-robot.yml
+++ b/.github/workflows/issue-robot.yml
@@ -22,12 +22,113 @@ on:
issues:
types: [opened]
+permissions:
+ issues: write
+
jobs:
- build:
+ translate:
runs-on: ubuntu-latest
+ if: github.actor != 'github-actions[bot]'
steps:
- - uses: tomsun28/[email protected]
+ - uses: actions/github-script@v7
with:
- # it is not necessary to decide whether you need to modify the issue
header content
- IS_MODIFY_TITLE: false
- CUSTOM_BOT_NOTE: RoBot detected the issue body's language is not
English, translate it automatically. π―ππ»π§βπ€βπ§π«π§πΏβπ€βπ§π»π©πΎβπ€βπ¨πΏπ¬πΏ
+ script: |
+ const isComment = context.eventName === 'issue_comment';
+ const text = isComment
+ ? context.payload.comment.body
+ : context.payload.issue.body;
+
+ if (!text || !text.trim()) return;
+
+ // Skip bot users and our own translation comments
+ const actor = isComment ? context.payload.comment.user :
context.payload.issue.user;
+ if (actor.type === 'Bot') return;
+ if (text.startsWith('> Bot detected the issue body')) return;
+
+ // Count script-specific characters (excludes emoji and symbols)
+ const cjk =
(text.match(/[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff]/g) || []).length;
+ const kana = (text.match(/[\u3040-\u30ff]/g) || []).length;
+ const hangul = (text.match(/[\uac00-\ud7af]/g) || []).length;
+ const cyrillic = (text.match(/[\u0400-\u04ff]/g) || []).length;
+ const arabic =
(text.match(/[\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff]/g) || []).length;
+ const devanagari = (text.match(/[\u0900-\u097f]/g) || []).length;
+ const thai = (text.match(/[\u0e00-\u0e7f]/g) || []).length;
+
+ const nonEnglishChars = cjk + kana + hangul + cyrillic + arabic +
devanagari + thai;
+ if (nonEnglishChars / text.length < 0.1) return;
+
+ // Detect source language
+ let srcLang = null;
+ if (kana > cjk * 0.1) srcLang = 'ja';
+ else if (hangul > cjk) srcLang = 'ko';
+ else if (cyrillic > 0) srcLang = 'ru';
+ else if (arabic > 0) srcLang = 'ar';
+ else if (devanagari > 0) srcLang = 'hi';
+ else if (thai > 0) srcLang = 'th';
+ else if (cjk > 0) srcLang = 'zh-CN';
+
+ if (!srcLang) {
+ core.info('Unable to determine source language, skipping.');
+ return;
+ }
+
+ // Redact common secret patterns before sending to translation API
+ let sanitized = text.substring(0, 3000);
+ sanitized = sanitized.replace(
+
/(token|key|secret|password|passwd|authorization|bearer)[\s:=]+\S+/gi,
+ '$1: [REDACTED]'
+ );
+
+ // Split text into chunks (MyMemory limit: 500 chars/request)
+ const chunks = [];
+ let remaining = sanitized;
+ while (remaining.length > 0) {
+ if (remaining.length <= 500) {
+ chunks.push(remaining);
+ break;
+ }
+ let i = remaining.lastIndexOf('\n', 500);
+ if (i < 150) i = remaining.lastIndexOf('γ', 500);
+ if (i < 150) i = remaining.lastIndexOf('. ', 500);
+ if (i < 0 || i < 150) i = 500;
+ else i++;
+ chunks.push(remaining.substring(0, i));
+ remaining = remaining.substring(i);
+ }
+
+ // Translate each chunk via MyMemory API (free, no key needed)
+ const translated = [];
+ for (const chunk of chunks) {
+ const params = new URLSearchParams({
+ q: chunk,
+ langpair: `${srcLang}|en`,
+ });
+ const res = await
fetch('https://api.mymemory.translated.net/get', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded'
},
+ body: params.toString(),
+ });
+ if (!res.ok) {
+ core.warning(`MyMemory API error: ${res.status}`);
+ return;
+ }
+ const data = await res.json();
+ if (data.responseStatus !== 200) {
+ core.warning(`MyMemory error: ${data.responseDetails ||
data.responseStatus}`);
+ return;
+ }
+ translated.push(data.responseData.translatedText);
+ }
+
+ const truncNote = text.length > 3000
+ ? '\n\n> Note: original text was truncated due to length.'
+ : '';
+
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.payload.issue.number,
+ body: `> Bot detected the issue body's language is not English,
translate it automatically.${truncNote}\n\n${translated.join('')}`,
+ });
+
+ core.info(`Translated from ${srcLang} to en.`);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]