Skip to content

Commit 111d8d7

Browse files
committed
feat(locale): getLocale service standup
1 parent c853ce6 commit 111d8d7

File tree

9 files changed

+172
-24
lines changed

9 files changed

+172
-24
lines changed
Binary file not shown.

packages/services/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"jsdoc": "rimraf docs && jsdoc -c ./jsdoc.json ./README.md"
3535
},
3636
"dependencies": {
37+
"@carbon/ibmdotcom-utilities": "^1.1.0-alpha.591",
3738
"axios": "^0.19.0",
3839
"jsonp": "^0.2.1",
3940
"window-or-global": "^1.0.1"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import root from 'window-or-global';
2+
import axios from 'axios';
3+
import { ipcinfoCookie, geolocation } from '@carbon/ibmdotcom-utilities';
4+
5+
/**
6+
* @constant {string | string} Host for the Locale API call
7+
* @private
8+
*/
9+
const _host = process.env.TRANSLATION_HOST || 'https://www.ibm.com';
10+
11+
/**
12+
* @constant {string | string} CORS proxy for lower environment calls
13+
* @private
14+
*/
15+
const _proxy = process.env.CORS_PROXY || '';
16+
17+
/**
18+
* Locale API endpoint
19+
*
20+
* @type {string}
21+
* @private
22+
*/
23+
const _endpoint = `${_host}/common/v18/js/data/jsononly/locale`;
24+
25+
/**
26+
* Locale API class with method of fetching user's locale for
27+
* ibm.com
28+
*/
29+
class LocaleAPI {
30+
/**
31+
* Gets the user's locale
32+
*
33+
* check if ipcinfo cookie exists (ipcinfoCookie util)
34+
* if not, retrieve the user's locale through geolocation util + gets user's
35+
* browser language preference then set the cookie
36+
*
37+
* @returns {object} object with lc and cc
38+
* @example
39+
* import { LocaleAPI } from '@carbon/ibmdotcom-services';
40+
*
41+
* async function getLocale() {
42+
* const locale = await LocaleAPI.getLocale();
43+
* return locale;
44+
* }
45+
*/
46+
static async getLocale() {
47+
const cookie = ipcinfoCookie.get();
48+
if (cookie && cookie.cc && cookie.lc) {
49+
return cookie;
50+
} else {
51+
const cc = await geolocation();
52+
53+
/**
54+
* get language preference from browser
55+
* returns in en-US format so will need to extract language only
56+
*/
57+
const lang = root.navigator.language;
58+
59+
const lc = lang.split('-')[0];
60+
61+
if (cc && lc) {
62+
const list = await this.getList();
63+
const verifiedCodes = this.verifyLocale(cc, lc, list);
64+
65+
// set the ipcInfo cookie
66+
ipcinfoCookie.set(verifiedCodes);
67+
68+
return verifiedCodes;
69+
}
70+
}
71+
}
72+
73+
/**
74+
* Get the country list of all supported countries and their languages
75+
*
76+
* @returns {Promise <any>} promise object
77+
*
78+
* @example
79+
* import { LocaleAPI } from '@carbon/ibmdotcom-services';
80+
*
81+
* function async getLocale() {
82+
* const list = await LocaleAPI.getList();
83+
* }
84+
*/
85+
static async getList() {
86+
const url = `${_proxy}${_endpoint}/usen-locale.json`;
87+
88+
return await axios
89+
.get(url, {
90+
headers: {
91+
'Content-Type': 'application/json; charset=utf-8',
92+
},
93+
})
94+
.then(response => response.data);
95+
}
96+
97+
/**
98+
* Verify that the cc and lc combo is in the list of
99+
* supported cc-lc combos
100+
*
101+
* @param {string} cc country code
102+
* @param {string} lc language code
103+
* @param {object} list country list
104+
*
105+
* @returns {object} object with lc and cc
106+
* @example
107+
* import { LocaleAPI } from '@carbon/ibmdotcom-services';
108+
*
109+
* async function getLocale() {
110+
* const cc = 'us';
111+
* const lc = 'en'
112+
* const locale = await LocaleAPI.verifyLocale(cc, lc, data);
113+
* return locale;
114+
* }
115+
*/
116+
static verifyLocale(cc, lc, list) {
117+
let priorityLC;
118+
let locale;
119+
120+
const language =
121+
list &&
122+
list.regionList.forEach(region =>
123+
region.countryList.forEach(country => {
124+
const code = country.locale[0][0].split('-');
125+
const countryCode = code[1];
126+
const languageCode = code[0];
127+
if (countryCode === cc && languageCode === lc) {
128+
locale = { cc, lc };
129+
}
130+
// save the priority language associated with the user's country code
131+
else if (countryCode === cc && !priorityLC) {
132+
priorityLC = languageCode;
133+
}
134+
})
135+
);
136+
if (!language && priorityLC) {
137+
locale = { cc, lc: priorityLC };
138+
}
139+
return locale;
140+
}
141+
}
142+
143+
export default LocaleAPI;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Copyright IBM Corp. 2016, 2018
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
export { default as LocaleAPI } from './Locale';

packages/services/src/services/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
export * from './Analytics';
99
export * from './DDO';
10+
export * from './Locale';
1011
export * from './MarketingSearch';
1112
export * from './Profile';
1213
export * from './SearchTypeahead';

packages/utilities/src/utilities/geolocation/__tests__/geolocation.test.js

+2-11
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,10 @@ mockAxios.get.mockImplementationOnce(() =>
1010
);
1111

1212
describe('Geolocation utility', () => {
13-
it('should return an object with the expected cc and lc', async () => {
14-
Object.defineProperty(window.navigator, 'language', {
15-
writable: true,
16-
value: 'en',
17-
});
18-
13+
it('should return an object with the expected cc', async () => {
1914
const info = await geolocation();
2015
const endpoint = process.env.GEO_API;
21-
const expected = {
22-
cc: 'us',
23-
lc: 'en',
24-
};
25-
expect(info).toStrictEqual(expected);
16+
expect(info).toBe('us');
2617
expect(mockAxios.get).toHaveBeenCalledWith(endpoint, {
2718
headers: {
2819
'Content-Type': 'application/json; charset=utf-8',
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import axios from 'axios';
2-
import root from 'window-or-global';
32

43
const _endpoint = process.env.GEO_API;
54
/**
65
* Utility to retrieve user's country code based on their IP address
7-
* and the language code from the browser language preference
86
*
97
* @example
108
* import { geolocation } from '@carbon/ibmdotcom-utilities';
119
*
1210
* const locationInfo = await geolocation();
1311
*
14-
* @returns {object} object with cc and lc data
12+
* @returns {string} country cc (cc)
1513
*
1614
*/
1715
async function geolocation() {
@@ -25,12 +23,7 @@ async function geolocation() {
2523

2624
const cc = location && location.country;
2725

28-
// get language preference from browser
29-
const lc = root.navigator.language;
30-
31-
if (cc && lc) {
32-
return { cc, lc };
33-
} else return;
26+
return cc;
3427
}
3528

3629
export default geolocation;

packages/utilities/src/utilities/ipcinfoCookie/ipcinfoCookie.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,18 @@ class ipcinfoCookie {
4242
* set the ipcInfo cookie
4343
* takes care of converting to string and encoding
4444
*
45-
* @param {string} cc country coude
46-
* @param {string} lc language code
45+
* @param {object} params params object
46+
* @param {string} params.cc country code
47+
* @param {string} params.lc language code
4748
*
4849
* @example
4950
* import { ipcinfoCookie } from '@carbon/ibmdotcom-utilities';
5051
*
51-
* ipcinfoCookie.set("us", "en");
52+
* const locale = {cc: 'us', lc: 'en'}
53+
* ipcinfoCookie.set(locale);
5254
*
5355
*/
54-
static set(cc, lc) {
56+
static set({ cc, lc }) {
5557
const info = `cc=${cc};lc=${lc}`;
5658

5759
Cookies.set(_cookieName, encodeURIComponent(info));

yarn.lock

+9
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,15 @@
926926
dependencies:
927927
window-or-global "^1.0.1"
928928

929+
"@carbon/ibmdotcom-utilities@^1.1.0-alpha.591":
930+
version "1.1.0-alpha.592"
931+
resolved "https://registry.yarnpkg.com/@carbon/ibmdotcom-utilities/-/ibmdotcom-utilities-1.1.0-alpha.592.tgz#77c68024ff35e68e08375cdb8fc9dcf48d22029b"
932+
integrity sha512-mhQAwCj6w2vWdU53vKL7oW6BJdljVvzAbqONQAVqdgwx7pOx2sp+NIKlIsw7whNfOJrpZqYL3RiedCKQlzHFFQ==
933+
dependencies:
934+
axios "^0.19.0"
935+
js-cookie "^2.2.1"
936+
window-or-global "^1.0.1"
937+
929938
"@carbon/icon-helpers@10.4.0":
930939
version "10.4.0"
931940
resolved "https://registry.yarnpkg.com/@carbon/icon-helpers/-/icon-helpers-10.4.0.tgz#771ba51efcaa9d2be03800f8e0f50c7aa779febf"

0 commit comments

Comments
 (0)