Skip to content
Permalink
Browse files
feat: translate the issue automatically if the language is not English.
  • Loading branch information
plainheart committed Feb 7, 2021
1 parent afb1a66 commit abbf83496462d65d4a086efc31ce592241f2391f
Showing 9 changed files with 154 additions and 42 deletions.
@@ -1,3 +1,13 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 4
indent_type = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
@@ -91,7 +91,7 @@ module.exports = (app) => {

app.on(['pull_request.opened'], async context => {
const isCore = isCommitter(
context.payload.pull_request.author_association,
context.payload.pull_request.author_association,
context.payload.pull_request.user.login
);
let commentText = isCore

Some generated files are not rendered by default. Learn more.

@@ -21,6 +21,8 @@
"test:watch": "jest --watch --notify --notifyMode=change --coverage"
},
"dependencies": {
"@vitalets/google-translate-api": "^5.0.0",
"franc": "^5.0.0",
"probot": "^11.0.6"
},
"devDependencies": {
@@ -1,8 +1,7 @@
const text = require('./text');
const { isCommitter } = require('./coreCommitters');

const REG_CHN_CHAR = /[\u4e00-\u9fa5]/g;
const MAX_CHN_CHAR_COUNT = 8;
const { removeCodeAndComment } = require('./util')
const { detectEnglish } = require('./translator')

class Issue {
constructor(context) {
@@ -61,24 +60,16 @@ class Issue {
this.addLabels.push(this.issueType);

const isInEnglish = this._contain('This issue is in English');
if (isInEnglish && !this._isMainlyUsingChinese()) {
if (isInEnglish &&
detectEnglish(removeCodeAndComment(this.title)) &&
detectEnglish(removeCodeAndComment(this.body))) {
this.addLabels.push('en');
}
}

_contain(txt) {
return this.body.indexOf(txt) > -1;
}

_isMainlyUsingChinese() {
const titleMatch = this.title.match(REG_CHN_CHAR);
// if title is mainly using Chinese, no need to check body
if (titleMatch && titleMatch.length > MAX_CHN_CHAR_COUNT) {
return true;
}
const bodyMatch = this.body.match(REG_CHN_CHAR);
return bodyMatch && bodyMatch.length > MAX_CHN_CHAR_COUNT;
}
}

module.exports = Issue;
@@ -1,30 +1,29 @@
const { createLogger, format, transports } = require('winston');
require('winston-daily-rotate-file');
const { SPLAT } = require('triple-beam');
const { combine, timestamp, label, splat, printf } = format;

const drfTransport = new transports.DailyRotateFile({
dirname: 'log',
filename: 'bot-%DATE%.log',
datePattern: 'YYYY-MM-DD',
maxSize: '1m',
maxFiles: '30d',
createSymlink: true,
zippedArchive: true
dirname: 'log',
filename: 'bot-%DATE%.log',
datePattern: 'YYYY-MM-DD',
maxSize: '1m',
maxFiles: '30d',
createSymlink: true,
zippedArchive: true
});

const errorStackHandler = format(e => {
if (e.name === 'AggregateError') {
return Object.assign({}, e, {
message: e.message,
stack: e.errors.map(err => err.stack).join('')
+ (e.event ? `\nEvent: ${JSON.stringify(e.event, null, 2)}` : '')
message: e.message,
stack: e.errors.map(err => err.stack).join('')
+ (e.event ? `\nEvent: ${JSON.stringify(e.event, null, 2)}` : '')
});
}
if (e instanceof Error) {
return Object.assign({}, e, {
message: e.message,
stack: e.stack
message: e.message,
stack: e.stack
});
}
return e;
@@ -39,13 +38,13 @@ const logger = createLogger({
],
exitOnError: false,
format: combine(
label({ label: 'BOT' }),
timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
errorStackHandler(),
splat(),
printf(({ level, message, label, timestamp, stack }) => {
return `${timestamp} [${label}] ${level}: ${message} ${stack || ''}`;
})
label({ label: 'BOT' }),
timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
errorStackHandler(),
splat(),
printf(({ level, message, label, timestamp, stack }) => {
return `${timestamp} [${label}] ${level}: ${message} ${stack || ''}`;
})
)
});

@@ -45,7 +45,6 @@ const MISSING_DEMO =
const ISSUE_TAGGED_PRIORITY_HIGH =
`This issue is labeled with \`priority: high\`, which means it's a frequently asked problem and we will fix it ASAP.`;


const PR_OPENED =
`Thanks for your contribution!
The community will review it ASAP. In the meanwhile, please checkout [the coding standard](https://echarts.apache.org/en/coding-standard.html) and Wiki about [How to make a pull request](https://github.com/apache/incubator-echarts/wiki/How-to-make-a-pull-request).`;
@@ -54,13 +53,12 @@ const PR_OPENED_BY_COMMITTER = PR_OPENED + `
The pull request is marked to be \`PR: author is committer\` because you are a committer of this project.`;

const PR_AWAITING_DOC = `Document changes are required in this PR. Please also make a PR to [apache/incubator-echarts-doc](https://github.com/apache/incubator-echarts-doc) for document changes. When the doc PR is merged, the maintainers will remove the \`PR: awaiting doc\` label.
`;
const PR_AWAITING_DOC = `Document changes are required in this PR. Please also make a PR to [apache/incubator-echarts-doc](https://github.com/apache/incubator-echarts-doc) for document changes. When the doc PR is merged, the maintainers will remove the \`PR: awaiting doc\` label.`;

const PR_MERGED =
`Congratulations! Your PR has been merged. Thanks for your contribution! 👍`;

const PR_NOT_MERGED = `I'm sorry your PR didn't get merged. Don't get frustrated. Maybe next time. 😛`
const PR_NOT_MERGED = `I'm sorry your PR didn't get merged. Don't get frustrated. Maybe next time. 😛`;

const LABEL_HOWTO =
`Sorry, but please ask *how-to* questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/echarts) or [segmentfault(中文)](https://segmentfault.com/t/echarts). You may also send an email about your question to dev@echarts.apache.org if you like.
@@ -76,7 +74,9 @@ As a free and open source project, ECharts also has limited maintainer bandwidth
For (1), we have decided to use the GitHub issue lists exclusively for work that has well-defined, actionable goals. Questions and open ended discussions should be posted to mediums that are better suited for them.
For (2), we have found that issues that do not provide proper information upfront usually results in terribly inefficient back-and-forth communication just to extract the basic information needed for actual triaging. This is exactly why we have created this app: to ensure that every issue is created with the necessary information, and to save time on both sides.`
For (2), we have found that issues that do not provide proper information upfront usually results in terribly inefficient back-and-forth communication just to extract the basic information needed for actual triaging. This is exactly why we have created this app: to ensure that every issue is created with the necessary information, and to save time on both sides.`;

const ISSUE_COMMENT_TRANSLATE_TIP = 'AT_ISSUE_AUTHOR It seems you are not using English, I\'ve helped translate the content automatically. To make your issue understood by more people, we\'d like to suggest using English next time. 🤗';

module.exports = {
NOT_USING_TEMPLATE,
@@ -92,5 +92,6 @@ module.exports = {
PR_AWAITING_DOC,
ISSUE_TAGGED_WAITING_AUTHOR,
ISSUE_TAGGED_EASY,
ISSUE_TAGGED_PRIORITY_HIGH
ISSUE_TAGGED_PRIORITY_HIGH,
ISSUE_COMMENT_TRANSLATE_TIP
};
@@ -0,0 +1,53 @@
const googleTranslate = require('@vitalets/google-translate-api');
const franc = require('franc');

/**
* To translate the raw sentence to English
* @param {string} rawContent sentence to be translated
* @return {object} { translated: string, lang: string }
*/
async function translate(rawContent) {
if (!rawContent || !(rawContent = rawContent.trim())) {
return;
}
try {
const res = await googleTranslate(
rawContent,
{
to: 'en',
tld: 'cn'
}
);
return {
translated: res.text,
lang: res.from.language.iso
};
}
catch (e) {
console.error('failed to translate', e);
}
}

/**
* To detect the languages of specified text
* @param {string} text
* @param {boolean} detectAll whether to return all detected languages
* @return {string | Array<[string, number]>}
*/
function detectLanguage(text, detectAll) {
if (!text || !(text = text.trim())) {
return;
}
return detectAll ? franc.all(text) : franc(text);
}

function detectEnglish(text) {
const lang = detectLanguage(text, true);
return lang[0][0] === 'eng' && (!lang[1] || lang[1][1] < 0.9);
}

module.exports = {
translate,
detectLanguage,
detectEnglish
}
@@ -0,0 +1,14 @@
function removeCodeAndComment(body) {
return body
.replace(/<!--[\w\W\r\n]*?-->/gmi, '')
.replace(/`{3}(.|\n)*`{3}/gmi, '');
}

function replaceAll(str, search, replacement) {
return str.replace(new RegExp(search, 'g'), replacement);
}

module.exports = {
removeCodeAndComment,
replaceAll
}

0 comments on commit abbf834

Please sign in to comment.