@salesforce/retail-react-app 1.0.0-preview.2 → 1.0.0-preview.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/_app/index.test.js +1 -1
- package/app/components/breadcrumb/index.jsx +1 -1
- package/app/hooks/use-einstein.js +57 -40
- package/app/hooks/use-einstein.test.js +22 -13
- package/app/hooks/use-product-view-modal.test.js +1 -1
- package/app/pages/checkout/index.jsx +1 -1
- package/app/pages/product-list/index.jsx +2 -1
- package/app/utils/locale.js +15 -6
- package/app/utils/locale.test.js +23 -0
- package/app/utils/test-utils.js +1 -1
- package/package.json +11 -9
- package/scripts/translations/compile-folder.js +26 -0
- package/scripts/translations/compile-pseudo.js +27 -0
- package/scripts/translations/utils.js +29 -0
- /package/{translations → app/static/translations}/compiled/de-DE.json +0 -0
- /package/{translations → app/static/translations}/compiled/en-GB.json +0 -0
- /package/{translations → app/static/translations}/compiled/en-US.json +0 -0
- /package/{translations → app/static/translations}/compiled/en-XA.json +0 -0
- /package/{translations → app/static/translations}/compiled/es-MX.json +0 -0
- /package/{translations → app/static/translations}/compiled/fr-FR.json +0 -0
- /package/{translations → app/static/translations}/compiled/it-IT.json +0 -0
- /package/{translations → app/static/translations}/compiled/ja-JP.json +0 -0
- /package/{translations → app/static/translations}/compiled/ko-KR.json +0 -0
- /package/{translations → app/static/translations}/compiled/pt-BR.json +0 -0
- /package/{translations → app/static/translations}/compiled/zh-CN.json +0 -0
- /package/{translations → app/static/translations}/compiled/zh-TW.json +0 -0
- /package/scripts/{extract-default-messages.js → translations/extract-default-messages.js} +0 -0
|
@@ -12,7 +12,7 @@ import App from '@salesforce/retail-react-app/app/components/_app/index.jsx'
|
|
|
12
12
|
import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
|
|
13
13
|
import {DEFAULT_LOCALE} from '@salesforce/retail-react-app/app/utils/test-utils'
|
|
14
14
|
import useMultiSite from '@salesforce/retail-react-app/app/hooks/use-multi-site'
|
|
15
|
-
import messages from '@salesforce/retail-react-app/translations/compiled/en-GB.json'
|
|
15
|
+
import messages from '@salesforce/retail-react-app/app/static/translations/compiled/en-GB.json'
|
|
16
16
|
import mockConfig from '@salesforce/retail-react-app/config/mocks/default'
|
|
17
17
|
jest.mock('../../hooks/use-multi-site', () => jest.fn())
|
|
18
18
|
let windowSpy
|
|
@@ -6,13 +6,17 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import {useMemo, useState} from 'react'
|
|
8
8
|
import {getConfig} from '@salesforce/pwa-kit-runtime/utils/ssr-config'
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
useCommerceApi,
|
|
11
|
+
useAccessToken,
|
|
12
|
+
useUsid,
|
|
13
|
+
useEncUserId,
|
|
14
|
+
useCustomerType
|
|
15
|
+
} from '@salesforce/commerce-sdk-react'
|
|
10
16
|
import {keysToCamel} from '@salesforce/retail-react-app/app/utils/utils'
|
|
11
17
|
|
|
12
18
|
export class EinsteinAPI {
|
|
13
|
-
constructor({host, einsteinId,
|
|
14
|
-
this.userId = userId
|
|
15
|
-
this.cookieId = cookieId
|
|
19
|
+
constructor({host, einsteinId, siteId, isProduction}) {
|
|
16
20
|
this.siteId = siteId
|
|
17
21
|
this.isProduction = isProduction
|
|
18
22
|
this.host = host
|
|
@@ -20,7 +24,7 @@ export class EinsteinAPI {
|
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
/**
|
|
23
|
-
* Given a POJO append the correct
|
|
27
|
+
* Given a POJO append the correct site and environment values
|
|
24
28
|
*
|
|
25
29
|
* @param {object} params
|
|
26
30
|
* @returns {object} The decorated body object.
|
|
@@ -31,20 +35,6 @@ export class EinsteinAPI {
|
|
|
31
35
|
|
|
32
36
|
const body = {...params}
|
|
33
37
|
|
|
34
|
-
// If we have an encrypted user id (authenticaed users only) use it as the `userId` otherwise
|
|
35
|
-
// we won't send a `userId` param for guest users.
|
|
36
|
-
if (this.userId) {
|
|
37
|
-
body.userId = this.userId
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Append the `usid` as the `cookieId` value if present. (It should always be present as long
|
|
41
|
-
// as the user is initilized)
|
|
42
|
-
if (this.cookieId) {
|
|
43
|
-
body.cookieId = this.cookieId
|
|
44
|
-
} else {
|
|
45
|
-
console.warn('Missing `cookieId`. For optimal results this value must be defined.')
|
|
46
|
-
}
|
|
47
|
-
|
|
48
38
|
// The first part of the siteId is the realm
|
|
49
39
|
if (this.siteId) {
|
|
50
40
|
body.realm = this.siteId.split('-')[0]
|
|
@@ -123,7 +113,6 @@ export class EinsteinAPI {
|
|
|
123
113
|
'x-cq-client-id': this.einsteinId
|
|
124
114
|
}
|
|
125
115
|
|
|
126
|
-
// Include `userId` and `cookieId` parameters.
|
|
127
116
|
if (body) {
|
|
128
117
|
body = this._buildBody(body)
|
|
129
118
|
}
|
|
@@ -393,20 +382,20 @@ const useEinstein = () => {
|
|
|
393
382
|
app: {einsteinAPI: config}
|
|
394
383
|
} = getConfig()
|
|
395
384
|
const {host, einsteinId, siteId, isProduction} = config
|
|
396
|
-
|
|
397
|
-
const
|
|
385
|
+
|
|
386
|
+
const {getUsidWhenReady} = useUsid()
|
|
387
|
+
const {getEncUserIdWhenReady} = useEncUserId()
|
|
388
|
+
const {isRegistered} = useCustomerType()
|
|
398
389
|
|
|
399
390
|
const einstein = useMemo(
|
|
400
391
|
() =>
|
|
401
392
|
new EinsteinAPI({
|
|
402
393
|
host,
|
|
403
394
|
einsteinId,
|
|
404
|
-
userId: encUserId,
|
|
405
|
-
cookieId: usid,
|
|
406
395
|
siteId,
|
|
407
396
|
isProduction
|
|
408
397
|
}),
|
|
409
|
-
[host, einsteinId,
|
|
398
|
+
[host, einsteinId, siteId, isProduction]
|
|
410
399
|
)
|
|
411
400
|
const [isLoading, setIsLoading] = useState(false)
|
|
412
401
|
const [recommendations, setRecommendations] = useState([])
|
|
@@ -440,51 +429,74 @@ const useEinstein = () => {
|
|
|
440
429
|
return reco
|
|
441
430
|
}
|
|
442
431
|
|
|
432
|
+
const getEventUserParameters = async () => {
|
|
433
|
+
return {
|
|
434
|
+
cookieId: await getUsidWhenReady(),
|
|
435
|
+
userId: isRegistered ? await getEncUserIdWhenReady() : undefined
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
443
439
|
return {
|
|
444
440
|
isLoading,
|
|
445
441
|
|
|
446
442
|
recommendations,
|
|
447
443
|
|
|
448
444
|
async sendViewProduct(...args) {
|
|
449
|
-
|
|
445
|
+
const userParameters = await getEventUserParameters()
|
|
446
|
+
return einstein.sendViewProduct(...args.concat(userParameters))
|
|
450
447
|
},
|
|
451
448
|
async sendViewSearch(...args) {
|
|
452
|
-
|
|
449
|
+
const userParameters = await getEventUserParameters()
|
|
450
|
+
return einstein.sendViewSearch(...args.concat(userParameters))
|
|
453
451
|
},
|
|
454
452
|
async sendClickSearch(...args) {
|
|
455
|
-
|
|
453
|
+
const userParameters = await getEventUserParameters()
|
|
454
|
+
return einstein.sendClickSearch(...args.concat(userParameters))
|
|
456
455
|
},
|
|
457
456
|
async sendViewCategory(...args) {
|
|
458
|
-
|
|
457
|
+
const userParameters = await getEventUserParameters()
|
|
458
|
+
return einstein.sendViewCategory(...args.concat(userParameters))
|
|
459
459
|
},
|
|
460
460
|
async sendClickCategory(...args) {
|
|
461
|
-
|
|
461
|
+
const userParameters = await getEventUserParameters()
|
|
462
|
+
return einstein.sendClickCategory(...args.concat(userParameters))
|
|
462
463
|
},
|
|
463
464
|
async sendViewPage(...args) {
|
|
464
|
-
|
|
465
|
+
const userParameters = await getEventUserParameters()
|
|
466
|
+
return einstein.sendViewPage(...args.concat(userParameters))
|
|
465
467
|
},
|
|
466
468
|
async sendBeginCheckout(...args) {
|
|
467
|
-
|
|
469
|
+
const userParameters = await getEventUserParameters()
|
|
470
|
+
return einstein.sendBeginCheckout(...args.concat(userParameters))
|
|
468
471
|
},
|
|
469
472
|
async sendCheckoutStep(...args) {
|
|
470
|
-
|
|
473
|
+
const userParameters = await getEventUserParameters()
|
|
474
|
+
return einstein.sendCheckoutStep(...args.concat(userParameters))
|
|
471
475
|
},
|
|
472
476
|
async sendViewReco(...args) {
|
|
473
|
-
|
|
477
|
+
const userParameters = await getEventUserParameters()
|
|
478
|
+
return einstein.sendViewReco(...args.concat(userParameters))
|
|
474
479
|
},
|
|
475
480
|
async sendClickReco(...args) {
|
|
476
|
-
|
|
481
|
+
const userParameters = await getEventUserParameters()
|
|
482
|
+
return einstein.sendClickReco(...args.concat(userParameters))
|
|
477
483
|
},
|
|
478
484
|
async sendAddToCart(...args) {
|
|
479
|
-
|
|
485
|
+
const userParameters = await getEventUserParameters()
|
|
486
|
+
return einstein.sendAddToCart(...args.concat(userParameters))
|
|
480
487
|
},
|
|
481
488
|
async getRecommenders(...args) {
|
|
482
489
|
return einstein.getRecommenders(...args)
|
|
483
490
|
},
|
|
484
|
-
async getRecommendations(recommenderName, products, args) {
|
|
491
|
+
async getRecommendations(recommenderName, products, ...args) {
|
|
485
492
|
setIsLoading(true)
|
|
486
493
|
try {
|
|
487
|
-
const
|
|
494
|
+
const userParameters = await getEventUserParameters()
|
|
495
|
+
const reco = await einstein.getRecommendations(
|
|
496
|
+
recommenderName,
|
|
497
|
+
products,
|
|
498
|
+
...args.concat(userParameters)
|
|
499
|
+
)
|
|
488
500
|
reco.recommenderName = recommenderName
|
|
489
501
|
const recommendations = await fetchRecProductDetails(reco)
|
|
490
502
|
setRecommendations(recommendations)
|
|
@@ -494,10 +506,15 @@ const useEinstein = () => {
|
|
|
494
506
|
setIsLoading(false)
|
|
495
507
|
}
|
|
496
508
|
},
|
|
497
|
-
async getZoneRecommendations(zoneName, products, args) {
|
|
509
|
+
async getZoneRecommendations(zoneName, products, ...args) {
|
|
498
510
|
setIsLoading(true)
|
|
499
511
|
try {
|
|
500
|
-
const
|
|
512
|
+
const userParameters = await getEventUserParameters()
|
|
513
|
+
const reco = await einstein.getZoneRecommendations(
|
|
514
|
+
zoneName,
|
|
515
|
+
products,
|
|
516
|
+
...args.concat(userParameters)
|
|
517
|
+
)
|
|
501
518
|
const recommendations = await fetchRecProductDetails(reco)
|
|
502
519
|
setRecommendations(recommendations)
|
|
503
520
|
} catch (err) {
|
|
@@ -18,8 +18,7 @@ import fetchMock from 'jest-fetch-mock'
|
|
|
18
18
|
const einsteinApi = new EinsteinAPI({
|
|
19
19
|
host: `http://localhost/test-path`,
|
|
20
20
|
einsteinId: 'test-id',
|
|
21
|
-
siteId: 'test-site-id'
|
|
22
|
-
cookieId: 'test-usid'
|
|
21
|
+
siteId: 'test-site-id'
|
|
23
22
|
})
|
|
24
23
|
|
|
25
24
|
const fetchOriginal = global.fetch
|
|
@@ -35,7 +34,7 @@ afterAll(() => {
|
|
|
35
34
|
|
|
36
35
|
describe('EinsteinAPI', () => {
|
|
37
36
|
test('viewProduct sends expected api request', async () => {
|
|
38
|
-
await einsteinApi.sendViewProduct(mockProduct)
|
|
37
|
+
await einsteinApi.sendViewProduct(mockProduct, {cookieId: 'test-usid'})
|
|
39
38
|
|
|
40
39
|
expect(fetch).toHaveBeenCalledWith(
|
|
41
40
|
'http://localhost/test-path/v3/activities/test-site-id/viewProduct',
|
|
@@ -52,7 +51,7 @@ describe('EinsteinAPI', () => {
|
|
|
52
51
|
|
|
53
52
|
test('viewSearch sends expected api request', async () => {
|
|
54
53
|
const searchTerm = 'tie'
|
|
55
|
-
await einsteinApi.sendViewSearch(searchTerm, mockSearchResults)
|
|
54
|
+
await einsteinApi.sendViewSearch(searchTerm, mockSearchResults, {cookieId: 'test-usid'})
|
|
56
55
|
expect(fetch).toHaveBeenCalledWith(
|
|
57
56
|
'http://localhost/test-path/v3/activities/test-site-id/viewSearch',
|
|
58
57
|
{
|
|
@@ -67,7 +66,7 @@ describe('EinsteinAPI', () => {
|
|
|
67
66
|
})
|
|
68
67
|
|
|
69
68
|
test('viewCategory sends expected api request', async () => {
|
|
70
|
-
await einsteinApi.sendViewCategory(mockCategory, mockSearchResults)
|
|
69
|
+
await einsteinApi.sendViewCategory(mockCategory, mockSearchResults, {cookieId: 'test-usid'})
|
|
71
70
|
expect(fetch).toHaveBeenCalledWith(
|
|
72
71
|
'http://localhost/test-path/v3/activities/test-site-id/viewCategory',
|
|
73
72
|
{
|
|
@@ -84,7 +83,7 @@ describe('EinsteinAPI', () => {
|
|
|
84
83
|
test('clickSearch sends expected api request', async () => {
|
|
85
84
|
const searchTerm = 'tie'
|
|
86
85
|
const clickedProduct = mockSearchResults.hits[0]
|
|
87
|
-
await einsteinApi.sendClickSearch(searchTerm, clickedProduct)
|
|
86
|
+
await einsteinApi.sendClickSearch(searchTerm, clickedProduct, {cookieId: 'test-usid'})
|
|
88
87
|
expect(fetch).toHaveBeenCalledWith(
|
|
89
88
|
'http://localhost/test-path/v3/activities/test-site-id/clickSearch',
|
|
90
89
|
{
|
|
@@ -100,7 +99,7 @@ describe('EinsteinAPI', () => {
|
|
|
100
99
|
|
|
101
100
|
test('clickCategory sends expected api request', async () => {
|
|
102
101
|
const clickedProduct = mockSearchResults.hits[0]
|
|
103
|
-
await einsteinApi.sendClickCategory(mockCategory, clickedProduct)
|
|
102
|
+
await einsteinApi.sendClickCategory(mockCategory, clickedProduct, {cookieId: 'test-usid'})
|
|
104
103
|
expect(fetch).toHaveBeenCalledWith(
|
|
105
104
|
'http://localhost/test-path/v3/activities/test-site-id/clickCategory',
|
|
106
105
|
{
|
|
@@ -116,7 +115,7 @@ describe('EinsteinAPI', () => {
|
|
|
116
115
|
|
|
117
116
|
test('viewPage sends expected api request', async () => {
|
|
118
117
|
const path = '/'
|
|
119
|
-
await einsteinApi.sendViewPage(path)
|
|
118
|
+
await einsteinApi.sendViewPage(path, {cookieId: 'test-usid'})
|
|
120
119
|
expect(fetch).toHaveBeenCalledWith(
|
|
121
120
|
'http://localhost/test-path/v3/activities/test-site-id/viewPage',
|
|
122
121
|
{
|
|
@@ -131,7 +130,7 @@ describe('EinsteinAPI', () => {
|
|
|
131
130
|
})
|
|
132
131
|
|
|
133
132
|
test('beginCheckout sends expected api request', async () => {
|
|
134
|
-
await einsteinApi.sendBeginCheckout(mockBasket)
|
|
133
|
+
await einsteinApi.sendBeginCheckout(mockBasket, {cookieId: 'test-usid'})
|
|
135
134
|
expect(fetch).toHaveBeenCalledWith(
|
|
136
135
|
'http://localhost/test-path/v3/activities/test-site-id/beginCheckout',
|
|
137
136
|
{
|
|
@@ -148,7 +147,9 @@ describe('EinsteinAPI', () => {
|
|
|
148
147
|
test('checkouStep sends expected api request', async () => {
|
|
149
148
|
const checkoutStepName = 'CheckoutStep'
|
|
150
149
|
const checkoutStep = 0
|
|
151
|
-
await einsteinApi.sendCheckoutStep(checkoutStepName, checkoutStep, mockBasket
|
|
150
|
+
await einsteinApi.sendCheckoutStep(checkoutStepName, checkoutStep, mockBasket, {
|
|
151
|
+
cookieId: 'test-usid'
|
|
152
|
+
})
|
|
152
153
|
expect(fetch).toHaveBeenCalledWith(
|
|
153
154
|
'http://localhost/test-path/v3/activities/test-site-id/checkoutStep',
|
|
154
155
|
{
|
|
@@ -163,7 +164,7 @@ describe('EinsteinAPI', () => {
|
|
|
163
164
|
})
|
|
164
165
|
|
|
165
166
|
test('addToCart sends expected api request', async () => {
|
|
166
|
-
await einsteinApi.sendAddToCart([mockAddToCartProduct])
|
|
167
|
+
await einsteinApi.sendAddToCart([mockAddToCartProduct], {cookieId: 'test-usid'})
|
|
167
168
|
expect(fetch).toHaveBeenCalledWith(
|
|
168
169
|
'http://localhost/test-path/v3/activities/test-site-id/addToCart',
|
|
169
170
|
{
|
|
@@ -178,7 +179,9 @@ describe('EinsteinAPI', () => {
|
|
|
178
179
|
})
|
|
179
180
|
|
|
180
181
|
test('clickRecommendation sends expected api request', async () => {
|
|
181
|
-
await einsteinApi.sendClickReco(mockRecommenderDetails, mockProduct
|
|
182
|
+
await einsteinApi.sendClickReco(mockRecommenderDetails, mockProduct, {
|
|
183
|
+
cookieId: 'test-usid'
|
|
184
|
+
})
|
|
182
185
|
expect(fetch).toHaveBeenCalledWith(
|
|
183
186
|
'http://localhost/test-path/v3/activities/test-site-id/clickReco',
|
|
184
187
|
{
|
|
@@ -193,7 +196,13 @@ describe('EinsteinAPI', () => {
|
|
|
193
196
|
})
|
|
194
197
|
|
|
195
198
|
test('viewRecommendation sends expected api request', async () => {
|
|
196
|
-
await einsteinApi.sendViewReco(
|
|
199
|
+
await einsteinApi.sendViewReco(
|
|
200
|
+
mockRecommenderDetails,
|
|
201
|
+
{
|
|
202
|
+
id: 'test-reco'
|
|
203
|
+
},
|
|
204
|
+
{cookieId: 'test-usid'}
|
|
205
|
+
)
|
|
197
206
|
expect(fetch).toHaveBeenCalledWith(
|
|
198
207
|
'http://localhost/test-path/v3/activities/test-site-id/viewReco',
|
|
199
208
|
{
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
DEFAULT_LOCALE,
|
|
19
19
|
renderWithProviders
|
|
20
20
|
} from '@salesforce/retail-react-app/app/utils/test-utils'
|
|
21
|
-
import messages from '@salesforce/retail-react-app/translations/compiled/en-GB.json'
|
|
21
|
+
import messages from '@salesforce/retail-react-app/app/static/translations/compiled/en-GB.json'
|
|
22
22
|
import {rest} from 'msw'
|
|
23
23
|
|
|
24
24
|
jest.mock('@salesforce/commerce-sdk-react', () => {
|
|
@@ -25,7 +25,7 @@ import {useUsid, useShopperOrdersMutation} from '@salesforce/commerce-sdk-react'
|
|
|
25
25
|
const Checkout = () => {
|
|
26
26
|
const {formatMessage} = useIntl()
|
|
27
27
|
const navigate = useNavigation()
|
|
28
|
-
const usid = useUsid()
|
|
28
|
+
const {usid} = useUsid()
|
|
29
29
|
const {step} = useCheckout()
|
|
30
30
|
const [error, setError] = useState()
|
|
31
31
|
const {data: basket} = useCurrentBasket()
|
|
@@ -402,7 +402,7 @@ const ProductList = (props) => {
|
|
|
402
402
|
<SelectedRefinements
|
|
403
403
|
filters={productSearchResult?.refinements}
|
|
404
404
|
toggleFilter={toggleFilter}
|
|
405
|
-
handleReset={
|
|
405
|
+
handleReset={resetFilters}
|
|
406
406
|
selectedFilterValues={productSearchResult?.selectedRefinements}
|
|
407
407
|
/>
|
|
408
408
|
</Box>
|
|
@@ -476,6 +476,7 @@ const ProductList = (props) => {
|
|
|
476
476
|
<SelectedRefinements
|
|
477
477
|
filters={productSearchResult?.refinements}
|
|
478
478
|
toggleFilter={toggleFilter}
|
|
479
|
+
handleReset={resetFilters}
|
|
479
480
|
selectedFilterValues={productSearchResult?.selectedRefinements}
|
|
480
481
|
/>
|
|
481
482
|
</Box>
|
package/app/utils/locale.js
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import PropTypes from 'prop-types'
|
|
9
|
+
import {getAssetUrl} from '@salesforce/pwa-kit-react-sdk/ssr/universal/utils'
|
|
10
|
+
import {getAppOrigin} from '@salesforce/pwa-kit-react-sdk/utils/url'
|
|
11
|
+
import fetch from 'cross-fetch'
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* Dynamically import the translations/messages for a given locale
|
|
@@ -21,11 +24,19 @@ export const fetchTranslations = async (locale) => {
|
|
|
21
24
|
: locale
|
|
22
25
|
: locale
|
|
23
26
|
|
|
24
|
-
let module
|
|
25
27
|
try {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
28
|
+
const file = `${getAppOrigin()}${getAssetUrl(
|
|
29
|
+
`static/translations/compiled/${targetLocale}.json`
|
|
30
|
+
)}`
|
|
31
|
+
const response = await fetch(file)
|
|
32
|
+
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
`Failed to fetch ${file}. Received the response: ${response.status} ${response.statusText}`
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return await response.json()
|
|
29
40
|
} catch (err) {
|
|
30
41
|
console.error(err)
|
|
31
42
|
console.log(
|
|
@@ -33,8 +44,6 @@ export const fetchTranslations = async (locale) => {
|
|
|
33
44
|
)
|
|
34
45
|
return {}
|
|
35
46
|
}
|
|
36
|
-
|
|
37
|
-
return module.default
|
|
38
47
|
}
|
|
39
48
|
|
|
40
49
|
/**
|
package/app/utils/locale.test.js
CHANGED
|
@@ -15,6 +15,29 @@ import {
|
|
|
15
15
|
|
|
16
16
|
import {DEFAULT_LOCALE, SUPPORTED_LOCALES} from '@salesforce/retail-react-app/app/utils/test-utils'
|
|
17
17
|
|
|
18
|
+
jest.mock('cross-fetch', () => {
|
|
19
|
+
return async (url) => {
|
|
20
|
+
const matched = url.match(/translations\/compiled\/(.+)\.json/)
|
|
21
|
+
if (!matched) {
|
|
22
|
+
throw new Error('Not seeing the expected url for the translation file')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const locale = matched[1]
|
|
26
|
+
const json = await import(`../static/translations/compiled/${locale}.json`)
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
ok: true,
|
|
30
|
+
json: () => Promise.resolve(json)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
jest.mock('@salesforce/pwa-kit-react-sdk/utils/url', () => {
|
|
35
|
+
return {getAppOrigin: () => ''}
|
|
36
|
+
})
|
|
37
|
+
jest.mock('@salesforce/pwa-kit-react-sdk/ssr/universal/utils', () => {
|
|
38
|
+
return {getAssetUrl: (url) => url}
|
|
39
|
+
})
|
|
40
|
+
|
|
18
41
|
const supportedLocales = SUPPORTED_LOCALES.map((locale) => locale.id)
|
|
19
42
|
const isMultiLocales = supportedLocales.length > 1
|
|
20
43
|
const nonSupportedLocale = 'nl-NL'
|
package/app/utils/test-utils.js
CHANGED
|
@@ -17,7 +17,7 @@ import {IntlProvider} from 'react-intl'
|
|
|
17
17
|
import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
|
|
18
18
|
import {PageContext, Region} from '@salesforce/commerce-sdk-react/components'
|
|
19
19
|
import {withReactQuery} from '@salesforce/pwa-kit-react-sdk/ssr/universal/components/with-react-query'
|
|
20
|
-
import fallbackMessages from '@salesforce/retail-react-app/translations/compiled/en-GB.json'
|
|
20
|
+
import fallbackMessages from '@salesforce/retail-react-app/app/static/translations/compiled/en-GB.json'
|
|
21
21
|
import mockConfig from '@salesforce/retail-react-app/config/mocks/default'
|
|
22
22
|
// Contexts
|
|
23
23
|
import {CurrencyProvider, MultiSiteProvider} from '@salesforce/retail-react-app/app/contexts'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/retail-react-app",
|
|
3
|
-
"version": "1.0.0-preview.
|
|
3
|
+
"version": "1.0.0-preview.3",
|
|
4
4
|
"license": "See license in LICENSE",
|
|
5
5
|
"author": "cc-pwa-kit@salesforce.com",
|
|
6
6
|
"ccExtensibility": {
|
|
@@ -12,12 +12,13 @@
|
|
|
12
12
|
"analyze-build": "cross-env MOBIFY_ANALYZE=true npm run build",
|
|
13
13
|
"build": "npm run build-translations && pwa-kit-dev build",
|
|
14
14
|
"build-translations": "npm run extract-default-translations && npm run compile-translations",
|
|
15
|
-
"compile-translations": "
|
|
16
|
-
"compile-translations:pseudo": "
|
|
17
|
-
"extract-default-translations": "node ./scripts/extract-default-messages.js en-US",
|
|
15
|
+
"compile-translations": "node ./scripts/translations/compile-folder.js translations",
|
|
16
|
+
"compile-translations:pseudo": "node ./scripts/translations/compile-pseudo.js translations/en-US.json",
|
|
17
|
+
"extract-default-translations": "node ./scripts/translations/extract-default-messages.js en-US",
|
|
18
18
|
"format": "pwa-kit-dev format \"**/*.{js,jsx}\"",
|
|
19
19
|
"lint": "pwa-kit-dev lint \"**/*.{js,jsx}\"",
|
|
20
20
|
"lint:fix": "npm run lint -- --fix",
|
|
21
|
+
"postinstall": "npm run compile-translations && npm run compile-translations:pseudo",
|
|
21
22
|
"push": "npm run build && pwa-kit-dev push",
|
|
22
23
|
"save-credentials": "pwa-kit-dev save-credentials",
|
|
23
24
|
"start": "cross-env NODE_ICU_DATA=node_modules/full-icu pwa-kit-dev start",
|
|
@@ -44,10 +45,10 @@
|
|
|
44
45
|
"@lhci/cli": "^0.11.0",
|
|
45
46
|
"@loadable/component": "^5.15.3",
|
|
46
47
|
"@peculiar/webcrypto": "^1.4.2",
|
|
47
|
-
"@salesforce/commerce-sdk-react": "1.0.0-preview.
|
|
48
|
-
"@salesforce/pwa-kit-dev": "3.0.0-preview.
|
|
49
|
-
"@salesforce/pwa-kit-react-sdk": "3.0.0-preview.
|
|
50
|
-
"@salesforce/pwa-kit-runtime": "3.0.0-preview.
|
|
48
|
+
"@salesforce/commerce-sdk-react": "1.0.0-preview.3",
|
|
49
|
+
"@salesforce/pwa-kit-dev": "3.0.0-preview.3",
|
|
50
|
+
"@salesforce/pwa-kit-react-sdk": "3.0.0-preview.3",
|
|
51
|
+
"@salesforce/pwa-kit-runtime": "3.0.0-preview.3",
|
|
51
52
|
"@tanstack/react-query": "^4.28.0",
|
|
52
53
|
"@tanstack/react-query-devtools": "^4.29.1",
|
|
53
54
|
"@testing-library/dom": "^9.0.1",
|
|
@@ -58,6 +59,7 @@
|
|
|
58
59
|
"bundlesize2": "^0.0.31",
|
|
59
60
|
"card-validator": "^8.1.1",
|
|
60
61
|
"cross-env": "^5.2.1",
|
|
62
|
+
"cross-fetch": "^3.1.4",
|
|
61
63
|
"focus-visible": "^5.2.0",
|
|
62
64
|
"framer-motion": "^10.12.9",
|
|
63
65
|
"full-icu": "^1.5.0",
|
|
@@ -101,5 +103,5 @@
|
|
|
101
103
|
"overrides": {
|
|
102
104
|
"nwsapi": "2.2.2"
|
|
103
105
|
},
|
|
104
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "0d435ccfb378e46a536e0eb4da3c9d3364ce89ea"
|
|
105
107
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023, Salesforce, Inc.
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
6
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
7
|
+
*/
|
|
8
|
+
/* eslint @typescript-eslint/no-var-requires: "off" */
|
|
9
|
+
const {exec} = require('child_process')
|
|
10
|
+
const {getOutputFolder} = require('./utils')
|
|
11
|
+
|
|
12
|
+
const main = () => {
|
|
13
|
+
const inputFolder = process.argv[2]
|
|
14
|
+
const outputFolder = getOutputFolder()
|
|
15
|
+
const command = `formatjs compile-folder --ast ${inputFolder} ${outputFolder}`
|
|
16
|
+
|
|
17
|
+
console.log('Compiling translations into the folder:', outputFolder)
|
|
18
|
+
exec(command, (err) => {
|
|
19
|
+
if (err) {
|
|
20
|
+
console.error(err)
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
main()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023, Salesforce, Inc.
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
6
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
7
|
+
*/
|
|
8
|
+
/* eslint @typescript-eslint/no-var-requires: "off" */
|
|
9
|
+
const {exec} = require('child_process')
|
|
10
|
+
const {getOutputFolder} = require('./utils')
|
|
11
|
+
|
|
12
|
+
const main = () => {
|
|
13
|
+
const inputFile = process.argv[2]
|
|
14
|
+
const locale = 'en-XA'
|
|
15
|
+
const outputFile = `${getOutputFolder()}/${locale}.json`
|
|
16
|
+
const command = `formatjs compile --ast ${inputFile} --out-file ${outputFile} --pseudo-locale ${locale}`
|
|
17
|
+
|
|
18
|
+
console.log('Compiling pseudo translation into the file:', outputFile)
|
|
19
|
+
exec(command, (err) => {
|
|
20
|
+
if (err) {
|
|
21
|
+
console.error(err)
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
main()
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023, Salesforce, Inc.
|
|
4
|
+
* All rights reserved.
|
|
5
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
6
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/* eslint @typescript-eslint/no-var-requires: "off" */
|
|
10
|
+
const fs = require('fs')
|
|
11
|
+
const path = require('path')
|
|
12
|
+
|
|
13
|
+
const getOutputFolder = () => {
|
|
14
|
+
const packagePath = path.join(process.cwd(), 'package.json')
|
|
15
|
+
const pkgJSON = JSON.parse(fs.readFileSync(packagePath))
|
|
16
|
+
|
|
17
|
+
const overridesDir = pkgJSON.ccExtensibility?.overridesDir
|
|
18
|
+
const extendsTemplate = pkgJSON.ccExtensibility?.extends
|
|
19
|
+
const outputFolder =
|
|
20
|
+
overridesDir && extendsTemplate
|
|
21
|
+
? path.join(overridesDir, 'app/static/translations/compiled')
|
|
22
|
+
: 'app/static/translations/compiled'
|
|
23
|
+
|
|
24
|
+
return outputFolder
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
getOutputFolder
|
|
29
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|