Grab the locale from the lang attribute from html, else
-check if ipcinfo cookie exists (ipcinfoCookie util)
-if not, retrieve the user's locale through DDO service + gets user's
-browser language preference then set the cookie
+
Gets the user's locale.
+
Grab the locale from the available information on the page in the following
+order:
/**
- * Copyright IBM Corp. 2020, 2023
+ * Copyright IBM Corp. 2020, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
@@ -39,7 +39,13 @@
Source: services/Locale/Locale.js
import root from 'window-or-global';
/**
- * @constant {string | string} Host for the Locale API call
+ * @typedef {object} Locale
+ * @property {string} cc The country code.
+ * @property {string} lc The language code.
+ */
+
+/**
+ * @constant {string | string} Host for the Locale API call.
* @private
*/
const _host =
@@ -48,9 +54,9 @@
Source: services/Locale/Locale.js
'https://1.www.s81c.com';
/**
- * Sets the default location if nothing is returned
+ * Sets the default location if nothing is returned.
*
- * @type {object}
+ * @type {Locale}
* @private
*/
const _localeDefault = {
@@ -59,7 +65,7 @@
Source: services/Locale/Locale.js
};
/**
- * Default display name for lang combination
+ * Default display name for lang combination.
*
* @type {string}
* @private
@@ -67,7 +73,7 @@
Source: services/Locale/Locale.js
const _localeNameDefault = 'United States — English';
/**
- * Locale API endpoint
+ * Locale API endpoint.
*
* @type {string}
* @private
@@ -75,7 +81,7 @@
};
/**
- * Session Storage key for country list
+ * Session Storage key for country list.
*
* @type {string}
* @private
@@ -103,38 +109,95 @@
Source: services/Locale/Locale.js
const _twoHours = 60 * 60 * 2000;
/**
- * Use the <html> lang attr to determine a return locale object
+ * The cache for in-flight or resolved requests for the country list, keyed by
+ * the initiating locale.
*
* @type {object}
* @private
*/
-const _getLocaleByLangAttr = () => {
+const _requestsList = {};
+
+/**
+ * Retrieves the default locale.
+ *
+ * @returns {Locale} The default locale.
+ */
+const _getLocaleDefault = () => _localeDefault;
+
+/**
+ * Use the <html> lang attr to determine a return locale object, or "false"
+ * when it's not available so the consumer can decide what to do next.
+ *
+ * @type {(Locale | boolean)}
+ * @private
+ */
+function _getLocaleFromLangAttr() {
if (root.document?.documentElement?.lang) {
const lang = root.document.documentElement.lang.toLowerCase();
+ const locale = {};
if (lang.indexOf('-') === -1) {
- return { lc: lang };
+ locale.lc = lang;
} else {
const codes = lang.split('-');
- return { cc: codes[1], lc: codes[0] };
+ locale.cc = codes[1];
+ locale.lc = codes[0];
}
- } else {
- return _localeDefault;
+ return locale;
+ }
+ return false;
+}
+
+/**
+ * Gets the locale from the cookie and returns it if both 'cc' and 'lc' values
+ * are present.
+ *
+ * @async
+ * @returns {Promise<Locale|boolean>} The cookie object if 'cc' and 'lc' values are present, otherwise false.
+ */
+const _getLocaleFromCookie = async () => {
+ const cookie = ipcinfoCookie.get();
+ if (cookie && cookie.cc && cookie.lc) {
+ await LocaleAPI.getList(cookie);
+ return cookie;
}
+ return false;
};
/**
- * The cache for in-flight or resolved requests for the country list, keyed by the initiating locale.
+ * Get the locale from the user's browser.
*
- * @type {object}
- * @private
+ * @async
+ * @returns {Promise<Locale|boolean>} The verified locale or false if not found.
*/
-const _requestsList = {};
+const _getLocaleFromBrowser = async () => {
+ try {
+ const cc = await DDOAPI.getLocation();
+
+ // Language preference from browser can return in either 'en-US' format or
+ // 'en' so will need to extract language only.
+ const lang = root.navigator.language;
+ const lc = lang.split('-')[0];
+
+ if (cc && lc) {
+ const list = await LocaleAPI.getList({ cc, lc });
+ const verifiedCodes = LocaleAPI.verifyLocale(cc, lc, list);
+
+ // Set the ipcInfo cookie.
+ ipcinfoCookie.set(verifiedCodes);
+
+ return verifiedCodes;
+ }
+ } catch (e) {
+ // Intentionally throw away the exception in favor of returning false.
+ }
+ return false;
+};
/**
- * Return a locale object based on the DDO API, or "false"
- * so the consumer can decide what to do next
+ * Return a locale object based on the DDO API, or "false" so the consumer can
+ * decide what to do next.
*
- * @type {(object | boolean)}
+ * @returns {(Locale | boolean)} Locale from the DDO, or "false" if not present.
* @private
*/
function _getLocaleFromDDO() {
@@ -178,8 +241,7 @@
Source: services/Locale/Locale.js
}
/**
- * Locale API class with method of fetching user's locale for
- * ibm.com
+ * Locale API class with method of fetching user's locale for ibm.com.
*/
class LocaleAPI {
/**
@@ -198,14 +260,18 @@
Source: services/Locale/Locale.js
}
/**
- * Gets the user's locale
+ * Gets the user's locale.
+ *
+ * Grab the locale from the available information on the page in the following
+ * order:
*
- * Grab the locale from the `lang` attribute from html, else
- * check if ipcinfo cookie exists (ipcinfoCookie util)
- * if not, retrieve the user's locale through DDO service + gets user's
- * browser language preference then set the cookie
+ * 1. DDO
+ * 2. HTML lang attribute
+ * 3. ipcInfo cookie
+ * 4. Browser (navigator.language)
+ * 5. Default (us-EN)
*
- * @returns {object} object with lc and cc
+ * @returns {Promise<Locale>} Locale object.
* @example
* import { LocaleAPI } from '@carbon/ibmdotcom-services';
*
@@ -215,69 +281,46 @@
Source: services/Locale/Locale.js
* }
*/
static async getLocale() {
- const cookie = ipcinfoCookie.get();
- const lang = await this.getLang();
-
- if (lang) {
- return lang;
- }
- // grab the locale from the cookie
- else if (cookie && cookie.cc && cookie.lc) {
- await this.getList(cookie);
- return cookie;
- } else {
- const cc = await DDOAPI.getLocation();
- /**
- * get language preference from browser
- * can return in either 'en-US' format or 'en' so will need to extract language only
- */
- const lang = root.navigator.language;
- const lc = lang.split('-')[0];
-
- if (cc && lc) {
- const list = await this.getList({ cc, lc });
- const verifiedCodes = this.verifyLocale(cc, lc, list);
-
- // set the ipcInfo cookie
- ipcinfoCookie.set(verifiedCodes);
-
- return verifiedCodes;
+ const localeGetters = [
+ _getLocaleFromDDO,
+ _getLocaleFromLangAttr,
+ _getLocaleFromCookie,
+ _getLocaleFromBrowser,
+ ];
+ for (const getter of localeGetters) {
+ const locale = await getter();
+ if (locale) {
+ return locale;
}
}
+ return _getLocaleDefault();
}
/**
- * Checks for DDO object to return the correct cc and lc
- * Otherwise gets those values from the <html> lang attribute
+ * Gets the user's locale.
*
- * @returns {object} locale object
+ * @returns {Promise<Locale>} Locale object.
* @example
* import { LocaleAPI } from '@carbon/ibmdotcom-services';
*
* function async getLocale() {
* const locale = await LocaleAPI.getLang();
* }
+ *
+ * @deprecated in favor of LocalAPI.getLocale.
*/
- static getLang() {
- return new Promise((resolve) => {
- const getLocaleFromDDO = _getLocaleFromDDO();
-
- if (getLocaleFromDDO) {
- resolve(getLocaleFromDDO);
- } else {
- resolve(_getLocaleByLangAttr());
- }
- });
+ static async getLang() {
+ return this.getLocale();
}
/**
- * This fetches the language display name based on language/locale combo
+ * This fetches the language display name based on locale.
*
- * @param {object} langCode lang code with cc and lc
- * @returns {Promise<string>} Display name of locale/language
+ * @param {(Locale | boolean)} locale (optional) If not given, uses LocaleAPI.getLocale logic.
+ * @returns {Promise<string>} Display name of locale/language.
*/
- static async getLangDisplay(langCode) {
- const lang = langCode ? langCode : await this.getLang();
+ static async getLangDisplay(locale) {
+ const lang = locale ? locale : await this.getLocale();
const list = await this.getList(lang);
// combines the countryList arrays
let countries = [];
@@ -309,12 +352,12 @@
Source: services/Locale/Locale.js
/**
* Get the country list of all supported countries and their languages
- * if it is not already stored in session storage
+ * if it is not already stored in session storage.
*
- * @param {object} params params object
- * @param {string} params.cc country code
- * @param {string} params.lc language code
- * @returns {Promise<any>} promise object
+ * @param {Locale} locale Locale object.
+ * @param {string} locale.cc Country code.
+ * @param {string} locale.lc Language code.
+ * @returns {Promise<any>} Promise object.
* @example
* import { LocaleAPI } from '@carbon/ibmdotcom-services';
*
@@ -330,12 +373,12 @@
Source: services/Locale/Locale.js
}
/**
- * Fetches the list data based on cc/lc combination
+ * Fetches the list data based on cc/lc combination.
*
- * @param {string} cc country code
- * @param {string} lc language code
- * @param {Function} resolve resolves the Promise
- * @param {Function} reject rejects the promise
+ * @param {string} cc Country code.
+ * @param {string} lc Language code.
+ * @param {Function} resolve Resolves the Promise.
+ * @param {Function} reject Rejects the promise.
*/
static fetchList(cc, lc, resolve, reject) {
const key = cc !== 'undefined' ? `${lc}-${cc}` : `${lc}`;
@@ -373,13 +416,12 @@
Source: services/Locale/Locale.js
}
/**
- * Verify that the cc and lc combo is in the list of
- * supported cc-lc combos
+ * Verify that the cc and lc combo is in the list of supported cc-lc combos.
*
- * @param {string} cc country code
- * @param {string} lc language code
- * @param {object} list country list
- * @returns {object} object with lc and cc
+ * @param {string} cc Country code.
+ * @param {string} lc Language code.
+ * @param {object} list Country list.
+ * @returns {object} Object with lc and cc.
* @example
* import { LocaleAPI } from '@carbon/ibmdotcom-services';
*
@@ -397,8 +439,8 @@