Skip to content

Commit

Permalink
Adds localization support for Caas + Milo (adobecom#476)
Browse files Browse the repository at this point in the history
  • Loading branch information
sanrai authored Feb 24, 2023
1 parent 504122f commit cc4967b
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 74 deletions.
2 changes: 1 addition & 1 deletion libs/blocks/caas-config/caas-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ const AdvancedPanel = () => {
prop="fallbackEndpoint"
type="text"}
/>
<${Input} label="Placeholders JSON" prop="placeholderUrl" type="text" />
<${Input} label="Map Text Strings From Word Doc" prop="placeholderUrl" type="text" />
<${Input} label="Tags Url" prop="tagsUrl" defaultValue=${defaultState.tagsUrl} type="text" />
<${MultiField}
onChange=${onChange('additionalRequestParams')}
Expand Down
65 changes: 51 additions & 14 deletions libs/blocks/caas/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable no-underscore-dangle */
import { loadScript, loadStyle } from '../../utils/utils.js';
import { loadScript, loadStyle, getConfig as pageConfigHelper } from '../../utils/utils.js';

const URL_ENCODED_COMMA = '%2C';

Expand All @@ -16,17 +16,53 @@ const fetchWithTimeout = async (resource, options = {}) => {
return response;
};

export const loadStrings = async (url) => {
// TODO: Loc based loading
const pageConfig = pageConfigHelper();
const pageLocales = Object.keys(pageConfig.locales || {});

export function getPageLocale(currentPath, locales = pageLocales) {
const possibleLocale = currentPath.split('/')[1];
if (locales.includes(possibleLocale)) {
return possibleLocale;
}
// defaults to en_US
return '';
}

export const loadStrings = async (
url,
pathname = window.location.pathname,
locales = pageLocales,
) => {
if (!url) return {};
const resp = await fetch(url);
if (!resp.ok) return {};
const json = await resp.json();
const convertToObj = (data) => data.reduce((obj, { key, val }) => {
obj[key] = val;
return obj;
}, {});
return convertToObj(json.data);
try {
const locale = getPageLocale(pathname, locales);
const localizedURL = new URL(url);
if (locale) {
localizedURL.pathname = `${locale}${localizedURL.pathname}`;
}
let resp = await fetch(`${localizedURL}.plain.html`);
if (!resp.ok) {
resp = await fetch(`${url}.plain.html`);
}
if (!resp.ok) {
return {};
}
const html = await resp.text();
const parser = new DOMParser();
const document = parser.parseFromString(html, 'text/html');
const nodes = document.querySelectorAll('.string-mappings > div');
return [...nodes].reduce((ans, parent) => {
const children = parent.querySelectorAll('div');
const key = children[0]?.innerText;
const val = children[1]?.innerHTML;
if (key) {
ans[key] = val || '';
}
return ans;
}, {});
} catch (err) {
return {};
}
};

export const loadCaasFiles = async () => {
Expand Down Expand Up @@ -190,12 +226,13 @@ const getFilterArray = async (state) => {
return filters;
};

export function arrayToObj (input=[]) {
export function arrayToObj(input = []) {
const obj = {};
if(!Array.isArray(input)){
if (!Array.isArray(input)) {
// eslint-disable-next-line no-param-reassign
input = [];
}
input.forEach(item => {
input.forEach((item) => {
if (item.key && item.value) {
obj[item.key] = item.value;
}
Expand Down
137 changes: 78 additions & 59 deletions test/blocks/caas/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { expect } from '@esm-bundle/chai';
import { stub } from 'sinon';
import { defaultState, getConfig, loadStrings, arrayToObj } from '../../../libs/blocks/caas/utils.js';
import { defaultState, getConfig, loadStrings, arrayToObj, getPageLocale } from '../../../libs/blocks/caas/utils.js';

const mockLocales = ['ar', 'br', 'ca', 'ca_fr', 'cl', 'co', 'la', 'mx', 'pe', '', 'africa', 'be_fr', 'be_en', 'be_nl',
'cy_en', 'dk', 'de', 'ee', 'es', 'fr', 'gr_en', 'ie', 'il_en', 'it', 'lv', 'lt', 'lu_de', 'lu_en', 'lu_fr', 'hu',
'mt', 'mena_en', 'nl', 'no', 'pl', 'pt', 'ro', 'sa_en', 'ch_de', 'si', 'sk', 'ch_fr', 'fi', 'se', 'ch_it', 'tr',
'ae_en', 'uk', 'at', 'cz', 'bg', 'ru', 'ua', 'il_he', 'ae_ar', 'mena_ar', 'sa_ar', 'au', 'hk_en', 'in', 'id_id',
'id_en', 'my_ms', 'my_en', 'nz', 'ph_en', 'ph_fil', 'sg', 'th_en', 'in_hi', 'th_th', 'cn', 'hk_zh', 'tw', 'jp', 'kr',
'langstore'];

const strings = {
collectionTitle: 'My Awesome Title',
Expand All @@ -16,6 +23,38 @@ const strings = {
sortType3: 'titleAsc',
};

function fileNotFoundResponse(){
return new Promise(function(resolve, reject){
resolve({
ok: false,
statusCode: 404,
text: () => {}
});
})
}

function htmlResponse(){
return new Promise(function(resolve){
resolve({
ok: true,
text: () => {
let fetchCalledWith = fetch.args[0].toString();
let fetchLocale = fetchCalledWith.split('/')[3];
return `
<div class="string-mappings">
<div>
<div>collectionTitle</div>
<div>${mockLocales.includes(fetchLocale) ? fetchLocale : ''} collection title</div>
<div>Card Collection Title</div>
<div></div>
<div></div>
</div>
</div>`
},
});
})
}

describe('additionalQueryParams', () => {
expect(arrayToObj([{key: 'a', value: 1}, {key: 'b', value: 2}])).to.be.eql({a: 1, b: 2})
expect(arrayToObj({})).to.be.eql({});
Expand All @@ -24,70 +63,50 @@ describe('loadStrings', () => {
const ogFetch = window.fetch;

beforeEach(() => {
window.fetch = stub().returns(
new Promise((resolve) => {
resolve({
ok: true,
json: () => ({
data: [
{
key: 'collectionTitle',
val: 'My Awesome Title',
},
{
key: 'onErrorTitle',
val: 'Error Loading Title',
},
{
key: 'onErrorDesc',
val: 'Error Desc',
},
{
key: 'prettyDateIntervalFormat',
val: '',
},
{
key: 'totalResults',
val: '{total} Results',
},
{
key: 'sortLabel1',
val: 'Featured Sort',
},
{
key: 'sortType1',
val: 'featured',
},
{
key: 'sortLabel2',
val: 'Most recent',
},
{
key: 'sortType2',
val: 'dateDesc',
},
{
key: 'sortLabel3',
val: 'Title',
},
{
key: 'sortType3',
val: 'titleAsc',
},
],
}),
});
}),
);
window.fetch = stub().returns(htmlResponse());
});

afterEach(() => {
window.fetch = ogFetch;
});

it('should fetch data from the given url', async () => {
const loadedStrings = await loadStrings('http://my.test.url');
expect(loadedStrings).to.eql(strings);
it('should fetch mappings for en_US', async () => {
const pathname = '/tools/caas';
const loadedStrings = await loadStrings('https://milo.adobe.com/drafts/caas/mappings', pathname, mockLocales);
let expected = {
collectionTitle: ' collection title',
};
expect(loadedStrings).to.eql(expected);
});

it('should be able to get correct page locale for en_US', () => {
let locale = getPageLocale('/tools/caas', mockLocales);
expect(locale).to.eql('');
});

for(let locale of mockLocales){
it('should be able to fetch mappings all other mockLocales ', async () => {
let expected = {
collectionTitle: `${locale} collection title`
};
const pathname = `/${locale}/tools/caas`;
const loadedStrings = await loadStrings(`https://milo.adobe.com/drafts/caas/mappings`, pathname, mockLocales);
expect(loadedStrings).to.eql(expected);
});
}

for(let locale of mockLocales) {
it('should be able to get correct page locale', () => {
let pageLocale = getPageLocale(`/${locale}/tools/caas`, mockLocales);
expect(locale).to.eql(pageLocale);
});
}

it('should be able to handle multiple 404s', async () => {
const pathname = `/fr/tools/caas`;
window.fetch = stub().returns(fileNotFoundResponse());
const loadedStrings = await loadStrings(`https://milo.adobe.com/drafts/caas/mappings`, pathname, mockLocales);
expect(loadedStrings).to.eql({});
});
});

Expand Down

0 comments on commit cc4967b

Please sign in to comment.