From 2e856859fe20b9ef37c540a3d43059a019797828 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Sat, 26 Jul 2025 15:23:22 -0500 Subject: [PATCH 1/7] use synonyms to accept zh-HK --- index.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 942ad48..b31ff2c 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,13 @@ +/* accept values from common locale selectors */ +const SYNONYMS = { + 'zh-CN': 'zh-Hans', + 'zh-Hans-CN': 'zh-Hans', + 'zh-HK': 'zh-Hant', + 'zh-Hant-HK': 'zh-Hant', + 'zh-TW': 'zh-Hant', + 'zh-Hant-TW': 'zh-Hant', +}; + /** * Create a new [Mapbox GL JS plugin](https://www.mapbox.com/blog/build-mapbox-gl-js-plugins/) that * modifies the layers of the map style to use the `text-field` that matches the browser language. @@ -115,7 +125,10 @@ function findStreetsSource(style) { * @returns {object} the modified style */ MapboxLanguage.prototype.setLanguage = function (style, language) { - if (this.supportedLanguages.indexOf(language) < 0) throw new Error(`Language ${ language } is not supported`); + language = SYNONYMS[language] || language; + if (this.supportedLanguages.indexOf(language) < 0) { + throw new Error(`Language ${ language } is not supported`); + } const streetsSource = this._languageSource || findStreetsSource(style); if (!streetsSource) return style; @@ -142,7 +155,8 @@ MapboxLanguage.prototype._initialStyleUpdate = function () { }; function browserLanguage(supportedLanguages) { - const language = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage); + let language = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage); + language = SYNONYMS[language] || language; const parts = language && language.split('-'); let languageCode = language; if (parts.length > 1) { From 5c1f5d990e37cd4d5b439909a48ad339a8402add Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Sat, 26 Jul 2025 15:31:05 -0500 Subject: [PATCH 2/7] include HK example --- examples/zh-HK.html | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 examples/zh-HK.html diff --git a/examples/zh-HK.html b/examples/zh-HK.html new file mode 100644 index 0000000..618f8df --- /dev/null +++ b/examples/zh-HK.html @@ -0,0 +1,35 @@ + + + + + Mapbox GL Language + + + + + + + + +
+ + + + From a9b8f5e5f1a97bfbec294c253f1dbf9772c6607d Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Sat, 26 Jul 2025 15:38:56 -0500 Subject: [PATCH 3/7] rename ALT_LOCALES --- index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index b31ff2c..795f1bb 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ /* accept values from common locale selectors */ -const SYNONYMS = { +const ALT_LOCALES = { 'zh-CN': 'zh-Hans', 'zh-Hans-CN': 'zh-Hans', 'zh-HK': 'zh-Hant', @@ -125,7 +125,7 @@ function findStreetsSource(style) { * @returns {object} the modified style */ MapboxLanguage.prototype.setLanguage = function (style, language) { - language = SYNONYMS[language] || language; + language = ALT_LOCALES[language] || language; if (this.supportedLanguages.indexOf(language) < 0) { throw new Error(`Language ${ language } is not supported`); } @@ -156,7 +156,7 @@ MapboxLanguage.prototype._initialStyleUpdate = function () { function browserLanguage(supportedLanguages) { let language = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage); - language = SYNONYMS[language] || language; + language = ALT_LOCALES[language] || language; const parts = language && language.split('-'); let languageCode = language; if (parts.length > 1) { From 055f4115e063499c5f55572170dba9d6bae12957 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Sat, 26 Jul 2025 16:18:23 -0500 Subject: [PATCH 4/7] use recursion to reduce long locales by piece --- index.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/index.js b/index.js index 795f1bb..4079aab 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,8 @@ -/* accept values from common locale selectors */ +/* accept lowercased values from common locale selectors */ const ALT_LOCALES = { - 'zh-CN': 'zh-Hans', - 'zh-Hans-CN': 'zh-Hans', - 'zh-HK': 'zh-Hant', - 'zh-Hant-HK': 'zh-Hant', - 'zh-TW': 'zh-Hant', - 'zh-Hant-TW': 'zh-Hant', + 'zh-cn': 'zh-Hans', + 'zh-hk': 'zh-Hant', + 'zh-tw': 'zh-Hant', }; /** @@ -125,8 +122,11 @@ function findStreetsSource(style) { * @returns {object} the modified style */ MapboxLanguage.prototype.setLanguage = function (style, language) { - language = ALT_LOCALES[language] || language; + language = ALT_LOCALES[language.toLowerCase()] || language; if (this.supportedLanguages.indexOf(language) < 0) { + if (language.indexOf('-') > -1) { + return this.setLanguage(style, language.slice(0, language.lastIndexOf('-'))); + } throw new Error(`Language ${ language } is not supported`); } const streetsSource = this._languageSource || findStreetsSource(style); @@ -154,16 +154,16 @@ MapboxLanguage.prototype._initialStyleUpdate = function () { this._map.setStyle(this.setLanguage(style, language)); }; -function browserLanguage(supportedLanguages) { - let language = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage); - language = ALT_LOCALES[language] || language; - const parts = language && language.split('-'); - let languageCode = language; - if (parts.length > 1) { - languageCode = parts[0]; +function browserLanguage(supportedLanguages, language) { + language = language || (navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage)); + language = ALT_LOCALES[language.toLowerCase()] || language; + + if (supportedLanguages.indexOf(language) > -1) { + return language; } - if (supportedLanguages.indexOf(languageCode) > -1) { - return languageCode; + if (language.indexOf('-') > -1) { + // reduce longer locales (en-US, zh-Hant-TW) to shorter forms + return browserLanguage(supportedLanguages, language.slice(0, language.lastIndexOf('-'))); } return null; } From 64fd04c4a529bebc7257c82fceed8d67392d1d3f Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Tue, 5 Aug 2025 07:12:01 -0500 Subject: [PATCH 5/7] add locales, change recursive calls to a while loop --- index.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index 4079aab..20ac89a 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,8 @@ const ALT_LOCALES = { 'zh-cn': 'zh-Hans', 'zh-hk': 'zh-Hant', + 'zh-mo': 'zh-Hant', + 'zh-sg': 'zh-Hans', 'zh-tw': 'zh-Hant', }; @@ -123,11 +125,13 @@ function findStreetsSource(style) { */ MapboxLanguage.prototype.setLanguage = function (style, language) { language = ALT_LOCALES[language.toLowerCase()] || language; - if (this.supportedLanguages.indexOf(language) < 0) { + + while (this.supportedLanguages.indexOf(language) < 0) { if (language.indexOf('-') > -1) { - return this.setLanguage(style, language.slice(0, language.lastIndexOf('-'))); + language = language.slice(0, language.lastIndexOf('-')); + } else { + throw new Error(`Language ${ language } is not supported`); } - throw new Error(`Language ${ language } is not supported`); } const streetsSource = this._languageSource || findStreetsSource(style); if (!streetsSource) return style; @@ -158,14 +162,15 @@ function browserLanguage(supportedLanguages, language) { language = language || (navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage)); language = ALT_LOCALES[language.toLowerCase()] || language; - if (supportedLanguages.indexOf(language) > -1) { - return language; - } - if (language.indexOf('-') > -1) { - // reduce longer locales (en-US, zh-Hant-TW) to shorter forms - return browserLanguage(supportedLanguages, language.slice(0, language.lastIndexOf('-'))); + while (supportedLanguages.indexOf(language) < 0) { + if (language.indexOf('-') > -1) { + // reduce longer locales (en-US, zh-Hant-TW) to shorter forms + language = language.slice(0, language.lastIndexOf('-')); + } else { + return null; + } } - return null; + return language; } MapboxLanguage.prototype.onAdd = function (map) { From 930ae1b22bc775b44718611791a5240e05ed27a4 Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Tue, 5 Aug 2025 07:19:43 -0500 Subject: [PATCH 6/7] add tests --- test/index.test.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/index.test.js b/test/index.test.js index 2349ae5..5ad0659 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -165,5 +165,40 @@ test('MapboxLanguage', (t) => { t.end(); }); + test('longer locales', (t) => { + const language = new MapboxLanguage(); + const layers = [{ + 'id': 'state-label-sm', + 'source': 'composite', + 'source-layer': 'state_label', + 'layout': { + 'text-letter-spacing': 0.15, + 'text-field': ['get', 'name'] + } + }]; + const style = makeStyle(layers); + + const enStyle = language.setLanguage(style, 'en-US'); + t.deepEqual(enStyle.layers[0].layout, { + 'text-letter-spacing': 0.15, + 'text-field': [ + 'coalesce', + ['get', 'name_en'], + ['get', 'name'] + ] + }, 'shorter locale name'); + + const zhStyle = language.setLanguage(style, 'zh-HK'); + t.deepEqual(zhStyle.layers[0].layout, { + 'text-letter-spacing': 0.15, + 'text-field': [ + 'coalesce', + ['get', 'name_zh-Hant'], + ['get', 'name'] + ] + }, 'zh hans/hant name'); + t.end(); + }); + t.end(); }); From 166447883c04af04ae1686b9837292ac589b217a Mon Sep 17 00:00:00 2001 From: Nick Doiron Date: Wed, 6 Aug 2025 20:25:44 -0500 Subject: [PATCH 7/7] remove change to browserLanguagefn --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 20ac89a..a893f7f 100644 --- a/index.js +++ b/index.js @@ -158,8 +158,8 @@ MapboxLanguage.prototype._initialStyleUpdate = function () { this._map.setStyle(this.setLanguage(style, language)); }; -function browserLanguage(supportedLanguages, language) { - language = language || (navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage)); +function browserLanguage(supportedLanguages) { + let language = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage); language = ALT_LOCALES[language.toLowerCase()] || language; while (supportedLanguages.indexOf(language) < 0) {