Skip to content

Commit 63cd03c

Browse files
committed
feat: localization support
1 parent 54db2ad commit 63cd03c

File tree

5 files changed

+130
-7
lines changed

5 files changed

+130
-7
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Support for localization.
13+
1014
### Fixed
1115

12-
- Improved JSDoc
16+
- Improved JSDoc.
1317

1418
## [0.1.0] - 2023-04-14
1519

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ Creates a client.
129129
| `options.baseUrl` | No | `string` | `window.location.pathname` | The base URL for the API. |
130130
| `options.fetchClient` | No | `Function` | `fetch` | The fetch client to use. Tested with `fetch` and `axios`. |
131131
| `options.fetchOptions` | No | `Object` | `{}` | The fetch client options. |
132+
| `options.locale` | No | `string` | `''` | The locale for every request. |
132133
| `options.onError` | No | `Function(error)` | `() => {}` | The function to call on error. |
133134
| `options.onResponse` | No | `Function(reponse)` | `(r) => r` | The function to call on response. |
134135
| `options.removeEmbedded` | No | `boolean` | `false` | Whether to remove the `_embedded` layer from the response if present. |

mock-api.json

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,87 @@
143143
"enabled": true,
144144
"responseMode": null,
145145
"type": "http"
146+
},
147+
{
148+
"uuid": "340d0baf-a233-4e54-9f33-521d2b94b251",
149+
"type": "http",
150+
"documentation": "",
151+
"method": "get",
152+
"endpoint": ":locale/:page.json",
153+
"responses": [
154+
{
155+
"uuid": "219e2896-e921-44b5-a0a9-06ee35c48da0",
156+
"body": "",
157+
"latency": 0,
158+
"statusCode": 200,
159+
"label": "",
160+
"headers": [],
161+
"bodyType": "DATABUCKET",
162+
"filePath": "",
163+
"databucketID": "48s8",
164+
"sendFileAsBody": false,
165+
"rules": [],
166+
"rulesOperator": "OR",
167+
"disableTemplating": false,
168+
"fallbackTo404": false,
169+
"default": true
170+
}
171+
],
172+
"enabled": true,
173+
"responseMode": null
174+
},
175+
{
176+
"uuid": "e4445514-4bbf-4bfd-bb6e-2b03b904d2ea",
177+
"documentation": "",
178+
"method": "get",
179+
"endpoint": ":locale/api/snippet-areas/:area",
180+
"responses": [
181+
{
182+
"uuid": "a86e39e6-5e1b-4339-8124-cd74d0a9ee97",
183+
"body": "",
184+
"latency": 0,
185+
"statusCode": 200,
186+
"label": "",
187+
"headers": [],
188+
"filePath": "",
189+
"sendFileAsBody": false,
190+
"rules": [],
191+
"rulesOperator": "OR",
192+
"disableTemplating": false,
193+
"fallbackTo404": false,
194+
"default": true,
195+
"databucketID": "48s8",
196+
"bodyType": "DATABUCKET"
197+
},
198+
{
199+
"uuid": "a647df05-8e5b-4b4e-916b-bf62a5cafde1",
200+
"body": "{\n \"message\": \"Snippet area does not exist\"\n}",
201+
"latency": 0,
202+
"statusCode": 404,
203+
"label": "",
204+
"headers": [],
205+
"bodyType": "INLINE",
206+
"filePath": "",
207+
"databucketID": "",
208+
"sendFileAsBody": false,
209+
"rules": [
210+
{
211+
"target": "params",
212+
"modifier": "area",
213+
"value": "non-existent",
214+
"invert": false,
215+
"operator": "equals"
216+
}
217+
],
218+
"rulesOperator": "OR",
219+
"disableTemplating": false,
220+
"fallbackTo404": false,
221+
"default": false
222+
}
223+
],
224+
"enabled": true,
225+
"responseMode": null,
226+
"type": "http"
146227
}
147228
],
148229
"proxyMode": false,
@@ -195,6 +276,13 @@
195276
"name": "Content response",
196277
"documentation": "",
197278
"value": "{\n \"content\": {\n \"title\": \"Lorem ipsum\"\n }\n}"
279+
},
280+
{
281+
"uuid": "5ae3fa4a-5348-4264-bba6-85e76e93473e",
282+
"id": "48s8",
283+
"name": "Locallized content response",
284+
"documentation": "",
285+
"value": "{\n \"content\": {\n \"title\": \"Hello world\"\n }\n}"
198286
}
199287
],
200288
"folders": [],
@@ -214,6 +302,14 @@
214302
{
215303
"type": "route",
216304
"uuid": "96421bb6-dfea-4dce-9a5b-3da89896feee"
305+
},
306+
{
307+
"type": "route",
308+
"uuid": "340d0baf-a233-4e54-9f33-521d2b94b251"
309+
},
310+
{
311+
"type": "route",
312+
"uuid": "e4445514-4bbf-4bfd-bb6e-2b03b904d2ea"
217313
}
218314
]
219315
}

src/client.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export default class Client {
77
baseUrl;
88
fetchClient;
99
fetchOptions;
10+
locale;
1011
onError;
1112
onResponse;
1213
removeEmbedded;
@@ -18,6 +19,7 @@ export default class Client {
1819
* @param {string} [options.baseUrl=window.location.origin] - The base URL for the API.
1920
* @param {function} [options.fetchClient=fetch.bind(window)] - The fetch client to use.
2021
* @param {Object} [options.fetchOptions={}] - The fetch client options.
22+
* @param {string} [options.locale=''] - The locale for every request.
2123
* @param {function} [options.onError=() => {}] - The function to call on error.
2224
* @param {function} [options.onResponse=(r) => r] - The function to call on response.
2325
* @param {boolean} [options.removeEmbedded=false] - Whether to remove the _embedded layer from the response if present.
@@ -26,13 +28,15 @@ export default class Client {
2628
baseUrl = window.location.origin,
2729
fetchClient = fetch.bind(window),
2830
fetchOptions = {},
31+
locale = '',
2932
onError = () => {},
3033
onResponse = (r) => r,
3134
removeEmbedded = false,
3235
}) {
3336
this.baseUrl = baseUrl;
3437
this.fetchClient = fetchClient;
3538
this.fetchOptions = fetchOptions;
39+
this.locale = locale;
3640
this.onError = onError;
3741
this.onResponse = onResponse;
3842
this.removeEmbedded = removeEmbedded;
@@ -43,10 +47,11 @@ export default class Client {
4347
*
4448
* @param {string} path - The path for the URL.
4549
* @param {Object} [params={}] - The query parameters for the URL.
50+
* @param {boolean} [withLocale=true] - Whether to prepend locale to path.
4651
* @returns {URL} The built URL.
4752
*/
48-
buildUrl(path, params = {}) {
49-
const url = new URL(path, this.baseUrl);
53+
buildUrl(path, params = {}, withLocale = true) {
54+
const url = new URL((this.locale && withLocale ? `/${this.locale}` : '') + path, this.baseUrl);
5055
url.search = new URLSearchParams(params);
5156

5257
return url;
@@ -56,15 +61,16 @@ export default class Client {
5661
* Sends a request to the API with the given path and query parameters.
5762
*
5863
* @param {string} path - The path for the request.
59-
* @param {Object} [params={}] - The query parameters for the request.
64+
* @param {Object} [params] - The query parameters for the request.
65+
* @param {boolean} [withLocale] - Whether to build a localized URL.
6066
* @returns {Promise<Object>} A Promise that resolves to the request's JSON.
6167
*/
62-
async request(path, params = {}) {
68+
async request(path, params, withLocale) {
6369
let response = null;
6470

6571
try {
6672
response = await this.fetchClient(
67-
this.buildUrl(path, params).toString(),
73+
this.buildUrl(path, params, withLocale).toString(),
6874
this.fetchOptions
6975
);
7076
} catch (error) {
@@ -98,7 +104,7 @@ export default class Client {
98104
* @returns {Promise<Object>} A Promise that resolves to the page data.
99105
*/
100106
getPageByPath(path) {
101-
return this.request(`${path}.json`);
107+
return this.request(`${path}.json`, null, false);
102108
}
103109

104110
/**

tests/client.spec.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,20 @@ test.describe('Client', () => {
8585
const data = await client.search('lorem');
8686
expect(data).toHaveProperty('_embedded.hits');
8787
});
88+
89+
test('should retrieve localized page data by path', async () => {
90+
const originalLocale = client.locale;
91+
client.locale = 'en';
92+
const data = await client.getPageByPath('/en/hello-world');
93+
client.locale = originalLocale;
94+
expect(data.content.title).toBe('Hello world');
95+
});
96+
97+
test('should retrieve localized snippet data by area name', async () => {
98+
const originalLocale = client.locale;
99+
client.locale = 'en';
100+
const data = await client.getSnippetByArea('default');
101+
client.locale = originalLocale;
102+
expect(data.content.title).toBe('Hello world');
103+
});
88104
});

0 commit comments

Comments
 (0)