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
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/index.js b/index.js
index 942ad48..a893f7f 100644
--- a/index.js
+++ b/index.js
@@ -1,3 +1,12 @@
+/* accept lowercased values from common locale selectors */
+const ALT_LOCALES = {
+ 'zh-cn': 'zh-Hans',
+ 'zh-hk': 'zh-Hant',
+ 'zh-mo': 'zh-Hant',
+ 'zh-sg': 'zh-Hans',
+ 'zh-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 +124,15 @@ 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 = ALT_LOCALES[language.toLowerCase()] || language;
+
+ while (this.supportedLanguages.indexOf(language) < 0) {
+ if (language.indexOf('-') > -1) {
+ language = language.slice(0, language.lastIndexOf('-'));
+ } else {
+ throw new Error(`Language ${ language } is not supported`);
+ }
+ }
const streetsSource = this._languageSource || findStreetsSource(style);
if (!streetsSource) return style;
@@ -142,16 +159,18 @@ MapboxLanguage.prototype._initialStyleUpdate = function () {
};
function browserLanguage(supportedLanguages) {
- const language = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
- const parts = language && language.split('-');
- let languageCode = language;
- if (parts.length > 1) {
- languageCode = parts[0];
- }
- if (supportedLanguages.indexOf(languageCode) > -1) {
- return languageCode;
+ let language = navigator.languages ? navigator.languages[0] : (navigator.language || navigator.userLanguage);
+ language = ALT_LOCALES[language.toLowerCase()] || language;
+
+ 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) {
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();
});