From 137bd72f6300afb68e76cc7b2dc699a81cf2f60c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 05:50:31 +0000 Subject: [PATCH 1/5] feat: add browser language detection --- js/i18n.js | 55 +++++++++++++++++++++++++++++- tests/aria-label-i18n.test.mjs | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/js/i18n.js b/js/i18n.js index 8725e92..e743f85 100644 --- a/js/i18n.js +++ b/js/i18n.js @@ -5,7 +5,7 @@ class I18nManager { constructor() { - this.currentLang = this.getLanguageFromURL() || 'zh'; + this.currentLang = this.getInitialLanguage(); this.translations = { zh: { title: 'AFX · 支付宝体验技术部 · 引领体验科技,驱动数字生活', @@ -35,6 +35,59 @@ class I18nManager { return urlParams.get('lang'); } + /** + * 规范化语言值 + */ + normalizeLanguage(lang) { + if (!lang) { + return null; + } + + const normalizedLang = lang.toLowerCase(); + + if (normalizedLang.startsWith('zh')) { + return 'zh'; + } + + if (normalizedLang.startsWith('en')) { + return 'en'; + } + + return null; + } + + /** + * 检测浏览器语言 + */ + detectBrowserLanguage() { + const browserLanguages = navigator.languages?.length + ? navigator.languages + : [navigator.language]; + + for (const lang of browserLanguages) { + const normalizedLang = this.normalizeLanguage(lang); + + if (normalizedLang) { + return normalizedLang; + } + } + + return 'zh'; + } + + /** + * 获取初始化语言 + */ + getInitialLanguage() { + const urlLanguage = this.getLanguageFromURL(); + + if (urlLanguage !== null) { + return this.normalizeLanguage(urlLanguage) || 'zh'; + } + + return this.detectBrowserLanguage(); + } + /** * 更新URL参数 */ diff --git a/tests/aria-label-i18n.test.mjs b/tests/aria-label-i18n.test.mjs index 8b6e336..ff57ef1 100644 --- a/tests/aria-label-i18n.test.mjs +++ b/tests/aria-label-i18n.test.mjs @@ -1,6 +1,7 @@ import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import test from 'node:test'; +import vm from 'node:vm'; const html = readFileSync(new URL('../index.html', import.meta.url), 'utf8'); const i18nScript = readFileSync( @@ -27,6 +28,46 @@ function getExternalLinks() { .filter(({ attributes }) => attributes.target === '_blank'); } +function createI18nManager({ search = '', language = 'zh-CN', languages } = {}) { + const context = { + window: { + location: { search }, + history: { replaceState() {} }, + }, + document: { + addEventListener() {}, + getElementById() { + return null; + }, + querySelector() { + return null; + }, + querySelectorAll() { + return []; + }, + dispatchEvent() {}, + documentElement: { lang: 'zh-CN' }, + }, + navigator: { + language, + languages: languages ?? [language], + }, + URL, + URLSearchParams, + CustomEvent: class { + constructor(type, init) { + this.type = type; + this.detail = init?.detail; + } + }, + }; + + vm.createContext(context); + vm.runInContext(`${i18nScript}\nglobalThis.I18nManager = I18nManager;`, context); + + return new context.I18nManager(); +} + test('external links provide localized aria-label values', () => { const externalLinks = getExternalLinks(); @@ -62,3 +103,24 @@ test('language switch updates localized aria-label values', () => { assert.match(i18nScript, /\[data-aria-zh\]\[data-aria-en\]/); assert.match(i18nScript, /setAttribute\(\s*['"]aria-label['"]/); }); + +test('defaults to browser English when no lang query is provided', () => { + const manager = createI18nManager({ language: 'en-US' }); + + assert.equal(manager.currentLang, 'en'); +}); + +test('defaults to browser Chinese when no lang query is provided', () => { + const manager = createI18nManager({ language: 'zh-TW' }); + + assert.equal(manager.currentLang, 'zh'); +}); + +test('lang query skips browser language detection', () => { + const manager = createI18nManager({ + search: '?lang=fr', + language: 'en-US', + }); + + assert.equal(manager.currentLang, 'zh'); +}); From cbec05f1fb5d19b1637822ede6d942f81e9bb7ea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 05:51:23 +0000 Subject: [PATCH 2/5] test: clarify language precedence coverage --- tests/aria-label-i18n.test.mjs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/aria-label-i18n.test.mjs b/tests/aria-label-i18n.test.mjs index ff57ef1..4518497 100644 --- a/tests/aria-label-i18n.test.mjs +++ b/tests/aria-label-i18n.test.mjs @@ -116,7 +116,16 @@ test('defaults to browser Chinese when no lang query is provided', () => { assert.equal(manager.currentLang, 'zh'); }); -test('lang query skips browser language detection', () => { +test('valid lang query takes precedence over browser language detection', () => { + const manager = createI18nManager({ + search: '?lang=en', + language: 'zh-CN', + }); + + assert.equal(manager.currentLang, 'en'); +}); + +test('invalid lang query falls back to Chinese without browser detection', () => { const manager = createI18nManager({ search: '?lang=fr', language: 'en-US', From 842c6f2ce678a54bf4de79ebb15eb261cce1cf53 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 05:51:53 +0000 Subject: [PATCH 3/5] test: clarify invalid lang fallback case --- tests/aria-label-i18n.test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/aria-label-i18n.test.mjs b/tests/aria-label-i18n.test.mjs index 4518497..91b3641 100644 --- a/tests/aria-label-i18n.test.mjs +++ b/tests/aria-label-i18n.test.mjs @@ -125,7 +125,7 @@ test('valid lang query takes precedence over browser language detection', () => assert.equal(manager.currentLang, 'en'); }); -test('invalid lang query falls back to Chinese without browser detection', () => { +test('invalid lang query ignores English browser locale and falls back to Chinese', () => { const manager = createI18nManager({ search: '?lang=fr', language: 'en-US', From 97c086d0a88b17d86f0971f9c223b6c61be8318a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 06:23:05 +0000 Subject: [PATCH 4/5] feat: change fallback language from Chinese to English --- js/i18n.js | 4 ++-- tests/aria-label-i18n.test.mjs | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/js/i18n.js b/js/i18n.js index e743f85..79b2c2e 100644 --- a/js/i18n.js +++ b/js/i18n.js @@ -72,7 +72,7 @@ class I18nManager { } } - return 'zh'; + return 'en'; } /** @@ -82,7 +82,7 @@ class I18nManager { const urlLanguage = this.getLanguageFromURL(); if (urlLanguage !== null) { - return this.normalizeLanguage(urlLanguage) || 'zh'; + return this.normalizeLanguage(urlLanguage) || 'en'; } return this.detectBrowserLanguage(); diff --git a/tests/aria-label-i18n.test.mjs b/tests/aria-label-i18n.test.mjs index 91b3641..42cf1b7 100644 --- a/tests/aria-label-i18n.test.mjs +++ b/tests/aria-label-i18n.test.mjs @@ -125,11 +125,17 @@ test('valid lang query takes precedence over browser language detection', () => assert.equal(manager.currentLang, 'en'); }); -test('invalid lang query ignores English browser locale and falls back to Chinese', () => { +test('invalid lang query ignores browser locale and falls back to English', () => { const manager = createI18nManager({ search: '?lang=fr', - language: 'en-US', + language: 'zh-CN', }); - assert.equal(manager.currentLang, 'zh'); + assert.equal(manager.currentLang, 'en'); +}); + +test('unrecognized browser language falls back to English', () => { + const manager = createI18nManager({ language: 'fr-FR', languages: ['fr-FR'] }); + + assert.equal(manager.currentLang, 'en'); }); From 0b4eefa699a1d136a3f5050139776c941062a0dc Mon Sep 17 00:00:00 2001 From: afc163 Date: Thu, 2 Jul 2026 16:11:43 +0800 Subject: [PATCH 5/5] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- tests/aria-label-i18n.test.mjs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/aria-label-i18n.test.mjs b/tests/aria-label-i18n.test.mjs index 42cf1b7..b6a4583 100644 --- a/tests/aria-label-i18n.test.mjs +++ b/tests/aria-label-i18n.test.mjs @@ -63,7 +63,15 @@ function createI18nManager({ search = '', language = 'zh-CN', languages } = {}) }; vm.createContext(context); - vm.runInContext(`${i18nScript}\nglobalThis.I18nManager = I18nManager;`, context); + + const i18nScriptWithoutInit = i18nScript.replace( + /\n?\s*new I18nManager\(\);\s*$/, + '' + ); + vm.runInContext( + `${i18nScriptWithoutInit}\nglobalThis.I18nManager = I18nManager;`, + context + ); return new context.I18nManager(); }