This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-website.git
The following commit(s) were added to refs/heads/master by this push:
new 54237d9b6ae [fix](i18n) Distinguish process identifiers from English
be (#4364)
54237d9b6ae is described below
commit 54237d9b6ae5f6f2bed49f0a660cd3d61b4b95ce
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Sun Oct 18 22:12:12 2026 +0100
[fix](i18n) Distinguish process identifiers from English be (#4364)
Whole-document glossary validation matched terms case-insensitively, so
ordinary English “be” and “Be” incorrectly required the Doris backend
identifier “BE”. In the real manual Korean batch, retries responded by
inserting backend references absent from both English community sources.
The generated candidate was rejected before merge. Lowercase target
prose could also incorrectly satisfy an actual uppercase process
identifier.
Match FE/BE process identifiers case-sensitively while preserving
existing Latin boundaries and other glossary matching. A regression
proves that a faithful Korean translation of a normal “can be” sentence
completes in one request without inventing BE. Another verifies that
real FE/BE remain required with their uppercase spelling, including next
to Japanese text.
Validation: both new regressions failed before the fix. Afterward, the
complete i18n/PoC/publish test command passed (209 passed, zero
failures, one existing Apache test skipped), and git diff checks passed.
This changes no rendered content, locale routing, translation state,
workflow triggers, permissions, or credentials. Korean generation
remains manual-only; the real bounded batch will be regenerated from
merged master for acceptance.
Co-authored-by: morningman <[email protected]>
---
scripts/i18n/__tests__/translate-document.test.cjs | 27 ++++++++++++++++++++++
scripts/i18n/document-checks.cjs | 6 +++--
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/scripts/i18n/__tests__/translate-document.test.cjs
b/scripts/i18n/__tests__/translate-document.test.cjs
index c37ac6159d0..1f587626062 100644
--- a/scripts/i18n/__tests__/translate-document.test.cjs
+++ b/scripts/i18n/__tests__/translate-document.test.cjs
@@ -92,6 +92,33 @@ test('Latin word matching permits BEFORE and prose number
localization; code sta
assert(wrongNumber.issues.some(item => item.check === 'protected-content'
&& /numeric values/.test(item.message)));
});
+test('ordinary English be does not request a backend term or a translation
retry', async () => {
+ let requests = 0;
+ const result = await translateWholeDocument({...options,
+ source: '# Guide\n\nBe aware that the email subject can be
anything.\n',
+ targetLocale: 'ko', targetScriptPattern: '[가-힣]',
+ adapter: {translateDocument: async ({feedback}) => {
+ requests++;
+ assert.deepEqual(feedback, []);
+ return {translation: '# 안내\n\n이메일 제목은 아무 내용이나 입력해도 됩니다.\n'};
+ }}});
+ assert.equal(requests, 1);
+ assert.deepEqual(result.generation.warnings, []);
+ assert(!result.target.includes('BE'));
+});
+
+test('actual FE and BE identifiers must retain their uppercase spelling',
async () => {
+ const input = {...options, source: '# Guide\n\nRestart FE and BE.\n',
+ glossary: {...glossary, keep: ['FE', 'BE']}};
+ const valid = await inspectDocument({...input, translation: '#
ガイド\n\nFEとBEを再起動します。\n'});
+ assert.deepEqual(valid.issues, []);
+ for (const term of ['FE', 'BE']) {
+ const invalid = await inspectDocument({...input,
+ translation: '# ガイド\n\n' + ['FE', 'BE'].map(item => item === term
? item.toLowerCase() : item).join('と') + 'を再起動します。\n'});
+ assert(invalid.issues.some(issue => issue.check === 'glossary' &&
issue.message === `Preserve product term: ${term}`));
+ }
+});
+
test('whole-document MDX accepts existing explicit heading IDs', async () => {
const source = '# Guide {#guide}\n\n<Widget label="Details" mode={1} />\n';
const result = await translateWholeDocument({...options, source,
extension: '.mdx',
diff --git a/scripts/i18n/document-checks.cjs b/scripts/i18n/document-checks.cjs
index 249a4a748bf..4a3f56900f7 100644
--- a/scripts/i18n/document-checks.cjs
+++ b/scripts/i18n/document-checks.cjs
@@ -118,8 +118,10 @@ async function inspectDocument({source, translation,
extension, glossary, target
throw new Error(`Translate the complete document into
${targetLocale}`);
});
// Word boundaries apply to Latin identifiers, including those next to
- // Japanese text. BEFORE must never count as the product term BE.
- const contains = (text, term) => new
RegExp(`(?<![A-Za-z0-9_])${term.replace(/[.*+?^${}()|[\]\\]/g,
'\\$&')}(?![A-Za-z0-9_])`, 'i').test(text);
+ // Japanese text. FE/BE process names are case-sensitive: ordinary English
+ // "be" and "Be" must not force a backend reference into a translation.
+ const contains = (text, term) => new
RegExp(`(?<![A-Za-z0-9_])${term.replace(/[.*+?^${}()|[\]\\]/g,
'\\$&')}(?![A-Za-z0-9_])`,
+ ['FE', 'BE'].includes(term) ? '' : 'i').test(text);
for (const term of glossary.keep) {
if (contains(source, term) && !contains(target, term))
issues.push({check: 'glossary', message: `Preserve product term:
${term}`});
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]