From 582bc7d9dfe698e893f5f155983ad3476aaaa0a4 Mon Sep 17 00:00:00 2001 From: lorretheboy Date: Thu, 25 Sep 2025 20:25:29 +0800 Subject: [PATCH 1/2] fix: translator logic to replace Chinese brackets --- scripts/utils/Translator/ChatGPTTranslator.ts | 6 +- scripts/utils/Translator/Translator.ts | 9 ++ tests/unit/ChatGPTTranslatorTest.ts | 13 ++ tests/unit/TranslatorTest.ts | 119 ++++++++++++++++++ 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 tests/unit/TranslatorTest.ts diff --git a/scripts/utils/Translator/ChatGPTTranslator.ts b/scripts/utils/Translator/ChatGPTTranslator.ts index 47aae46247aa..a0f19b50da94 100644 --- a/scripts/utils/Translator/ChatGPTTranslator.ts +++ b/scripts/utils/Translator/ChatGPTTranslator.ts @@ -35,11 +35,13 @@ class ChatGPTTranslator extends Translator { userPrompt: text, }); - if (this.validateTemplatePlaceholders(text, result) && this.validateTemplateHTML(text, result)) { + const fixedResult = this.fixChineseBracketsInMarkdown(result); + + if (this.validateTemplatePlaceholders(text, fixedResult) && this.validateTemplateHTML(text, fixedResult)) { if (attempt > 0) { console.log(`🙃 Translation succeeded after ${attempt + 1} attempts`); } - return result; + return fixedResult; } console.warn(`⚠️ Translation for "${text}" failed validation (attempt ${attempt + 1}/${ChatGPTTranslator.MAX_RETRIES + 1})`); diff --git a/scripts/utils/Translator/Translator.ts b/scripts/utils/Translator/Translator.ts index ff2f6263882d..24fd535265e9 100644 --- a/scripts/utils/Translator/Translator.ts +++ b/scripts/utils/Translator/Translator.ts @@ -35,6 +35,15 @@ abstract class Translator { return `${text.slice(0, 80)}${text.length > 80 ? '...' : ''}`; } + /** + * Replace Chinese full-width brackets 【 (U+3010) and 】 (U+3011) with normal ASCII brackets [ and ] + */ + public fixChineseBracketsInMarkdown(text: string): string { + return text + .replaceAll('\u3010', '[') // 【 + .replaceAll('\u3011', ']'); // 】 + } + /** * Validate that placeholders are all present and unchanged before and after translation. */ diff --git a/tests/unit/ChatGPTTranslatorTest.ts b/tests/unit/ChatGPTTranslatorTest.ts index 42dcc3830256..6fc008357dd1 100644 --- a/tests/unit/ChatGPTTranslatorTest.ts +++ b/tests/unit/ChatGPTTranslatorTest.ts @@ -66,4 +66,17 @@ describe('ChatGPTTranslator.performTranslation', () => { expect(MockedOpenAIUtils.prototype.promptChatCompletions).toHaveBeenCalledTimes(2); expect(result).toBe(validHTMLTranslation); }); + + it('fixes Chinese brackets in markdown syntax after translation', async () => { + const originalText = '[Click here](https://example.com)'; + const translatedWithChineseBrackets = '【点击这里】(https://example.com)'; + const expectedFixed = '[点击这里](https://example.com)'; + + (MockedOpenAIUtils.prototype.promptChatCompletions as jest.Mock).mockResolvedValueOnce(translatedWithChineseBrackets); + + // @ts-expect-error TS2445 + const result = await translator.performTranslation(targetLang, originalText); + + expect(result).toBe(expectedFixed); + }); }); diff --git a/tests/unit/TranslatorTest.ts b/tests/unit/TranslatorTest.ts new file mode 100644 index 000000000000..b3ce311d41d4 --- /dev/null +++ b/tests/unit/TranslatorTest.ts @@ -0,0 +1,119 @@ +import Translator from '@scripts/utils/Translator/Translator'; + +class TestTranslator extends Translator { + protected performTranslation(): Promise { + return Promise.resolve(''); + } +} + +describe('Translator - Chinese Brackets Fix', () => { + let translator: TestTranslator; + + beforeEach(() => { + translator = new TestTranslator(); + }); + + describe('fixChineseBracketsInMarkdown', () => { + it('should fix Chinese brackets in markdown links', () => { + const input = '【Click here】(https://example.com)'; + const expected = '[Click here](https://example.com)'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should fix Chinese brackets in markdown images', () => { + const input = '!【Alt text】(https://example.com/image.png)'; + const expected = '![Alt text](https://example.com/image.png)'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should fix Chinese brackets in reference-style links', () => { + const input = '【Link text】【ref-id】'; + const expected = '[Link text][ref-id]'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should fix Chinese brackets in reference definitions', () => { + const input = '【ref-id】: https://example.com "Title"'; + const expected = '[ref-id]: https://example.com "Title"'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should fix Chinese brackets in autolinks for URLs', () => { + const input = '【https://example.com】'; + const expected = '[https://example.com]'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should fix Chinese brackets in task list items', () => { + const input = '- 【x】 Completed task\n- 【 】 Incomplete task'; + const expected = '- [x] Completed task\n- [ ] Incomplete task'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should handle multiple markdown patterns in one text', () => { + const input = ` + Check out 【this link】(https://example.com) and this image !【screenshot】(image.png). + Also see 【reference】【1】 and the definition: + 【1】: https://reference.com + + Tasks: + - 【x】 Done + - 【 】 Todo + `.trim(); + + const expected = ` + Check out [this link](https://example.com) and this image ![screenshot](image.png). + Also see [reference][1] and the definition: + [1]: https://reference.com + + Tasks: + - [x] Done + - [ ] Todo + `.trim(); + + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should return original text if no Chinese brackets present', () => { + const input = '[Normal link](https://example.com) and regular text'; + const expected = '[Normal link](https://example.com) and regular text'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should handle empty string', () => { + const input = ''; + const expected = ''; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should handle nested markdown structures', () => { + const input = '【【nested】】(url)'; + const expected = '[[nested]](url)'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should handle task lists with different bullet points', () => { + const input = '* 【x】 Task 1\n+ 【 】 Task 2\n- 【x】 Task 3'; + const expected = '* [x] Task 1\n+ [ ] Task 2\n- [x] Task 3'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + + it('should handle indented task lists', () => { + const input = ' - 【x】 Indented task\n - 【 】 More indented'; + const expected = ' - [x] Indented task\n - [ ] More indented'; + const result = translator.fixChineseBracketsInMarkdown(input); + expect(result).toBe(expected); + }); + }); +}); From 307ff385c03218a63ddbf9380ec6465dfd9f01c2 Mon Sep 17 00:00:00 2001 From: lorretheboy Date: Thu, 25 Sep 2025 20:36:06 +0800 Subject: [PATCH 2/2] fix: spelling --- tests/unit/TranslatorTest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/TranslatorTest.ts b/tests/unit/TranslatorTest.ts index b3ce311d41d4..f3558817dd57 100644 --- a/tests/unit/TranslatorTest.ts +++ b/tests/unit/TranslatorTest.ts @@ -42,7 +42,7 @@ describe('Translator - Chinese Brackets Fix', () => { expect(result).toBe(expected); }); - it('should fix Chinese brackets in autolinks for URLs', () => { + it('should fix Chinese brackets for URLs', () => { const input = '【https://example.com】'; const expected = '[https://example.com]'; const result = translator.fixChineseBracketsInMarkdown(input);