@transifex/native 2.1.2 → 2.3.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@transifex/native",
3
- "version": "2.1.2",
3
+ "version": "2.3.1",
4
4
  "description": "Transifex Native for Javascript",
5
5
  "keywords": [
6
6
  "transifex",
package/src/TxNative.js CHANGED
@@ -35,6 +35,7 @@ export default class TxNative {
35
35
  this.currentLocale = '';
36
36
  this.locales = [];
37
37
  this.languages = [];
38
+ this.childInstances = [];
38
39
  }
39
40
 
40
41
  /**
@@ -52,7 +53,6 @@ export default class TxNative {
52
53
  */
53
54
  init(params) {
54
55
  const that = this;
55
-
56
56
  [
57
57
  'cdsHost',
58
58
  'token',
@@ -68,6 +68,7 @@ export default class TxNative {
68
68
  that[value] = params[value];
69
69
  }
70
70
  });
71
+ this.fetchedTags = {}; // {langCode: [tag1, tag2, ...], ...}
71
72
  }
72
73
 
73
74
  /**
@@ -159,23 +160,37 @@ export default class TxNative {
159
160
  * @returns {Promise}
160
161
  */
161
162
  async fetchTranslations(localeCode, params = {}) {
163
+ const filterTags = params.filterTags || this.filterTags;
164
+
162
165
  if (!params.refresh
163
- && this.cache.hasTranslations(localeCode)
164
166
  && !this.cache.isStale(localeCode)
165
- ) {
167
+ && (
168
+ (!filterTags && this.cache.hasTranslations(localeCode))
169
+ || (filterTags
170
+ && (this.fetchedTags[localeCode] || []).indexOf(filterTags) !== -1)
171
+ )) {
166
172
  return;
167
173
  }
168
174
 
175
+ if (filterTags) {
176
+ if (!(localeCode in this.fetchedTags)) {
177
+ this.fetchedTags[localeCode] = [];
178
+ }
179
+ if (this.fetchedTags[localeCode].indexOf(filterTags) === -1) {
180
+ this.fetchedTags[localeCode].push(filterTags);
181
+ }
182
+ }
183
+
169
184
  // contact CDS
170
185
  try {
171
- sendEvent(FETCHING_TRANSLATIONS, localeCode, this);
186
+ sendEvent(FETCHING_TRANSLATIONS, { localeCode, filterTags }, this);
172
187
  let response;
173
188
  let lastResponseStatus = 202;
174
189
  while (lastResponseStatus === 202) {
175
190
  /* eslint-disable no-await-in-loop */
176
191
  let url = `${this.cdsHost}/content/${localeCode}`;
177
- if (this.filterTags) {
178
- url = `${url}?filter[tags]=${this.filterTags}`;
192
+ if (filterTags) {
193
+ url = `${url}?filter[tags]=${filterTags}`;
179
194
  }
180
195
  response = await axios.get(url, {
181
196
  headers: {
@@ -197,13 +212,13 @@ export default class TxNative {
197
212
  }
198
213
  });
199
214
  this.cache.update(localeCode, hashmap);
200
- sendEvent(TRANSLATIONS_FETCHED, localeCode, this);
215
+ sendEvent(TRANSLATIONS_FETCHED, { localeCode, filterTags }, this);
201
216
  } else {
202
- sendEvent(TRANSLATIONS_FETCH_FAILED, localeCode, this);
217
+ sendEvent(TRANSLATIONS_FETCH_FAILED, { localeCode, filterTags }, this);
203
218
  throw new Error('Could not fetch translations');
204
219
  }
205
220
  } catch (err) {
206
- sendEvent(TRANSLATIONS_FETCH_FAILED, localeCode, this);
221
+ sendEvent(TRANSLATIONS_FETCH_FAILED, { localeCode, filterTags }, this);
207
222
  throw err;
208
223
  }
209
224
  }
@@ -285,14 +300,27 @@ export default class TxNative {
285
300
  * @returns {Promise}
286
301
  */
287
302
  async setCurrentLocale(localeCode) {
288
- if (this.isCurrent(localeCode)) return;
303
+ if (this.isCurrent(localeCode)) {
304
+ await this._syncInstances(this.childInstances);
305
+ return;
306
+ }
307
+
289
308
  if (!localeCode) {
309
+ // update controller
290
310
  this.currentLocale = '';
311
+ await this._syncInstances(this.childInstances);
291
312
  sendEvent(LOCALE_CHANGED, this.currentLocale, this);
292
313
  return;
293
314
  }
315
+
316
+ // Fetch translations for controller instance
294
317
  await this.fetchTranslations(localeCode);
295
318
  this.currentLocale = localeCode;
319
+
320
+ // Update children
321
+ await this._syncInstances(this.childInstances);
322
+
323
+ // Trigger controller change
296
324
  sendEvent(LOCALE_CHANGED, localeCode, this);
297
325
  }
298
326
 
@@ -312,4 +340,63 @@ export default class TxNative {
312
340
  await this.getLocales(params);
313
341
  return [...this.languages];
314
342
  }
343
+
344
+ /**
345
+ * Connect a child instance with this instance as controller.
346
+ * When the language is changing on this instance, all child
347
+ * instances will be updated as well.
348
+ *
349
+ * @param {*} instance
350
+ * @returns {Promise}
351
+ */
352
+ async controllerOf(instance) {
353
+ if (instance === this) {
354
+ throw new Error('Cannot add self as instance');
355
+ }
356
+ if (instance.childInstances.indexOf(this) !== -1) {
357
+ throw new Error('Cycle reference error, instance is controller of this');
358
+ }
359
+
360
+ this.childInstances.push(instance);
361
+ await this._syncInstances([instance]);
362
+
363
+ return instance;
364
+ }
365
+
366
+ /**
367
+ * Private function to sync controller with
368
+ * child instance.
369
+ *
370
+ * @param {Array} instances
371
+ * @memberof TxNative
372
+ */
373
+ async _syncInstances(instances) {
374
+ // update instance language
375
+ const localeCode = this.getCurrentLocale();
376
+
377
+ // update children instances
378
+ if (localeCode) {
379
+ for (let i = 0; i < instances.length; i++) {
380
+ // do not fetch language if not needed
381
+ if (instances[i].getCurrentLocale() !== localeCode) {
382
+ // Fetch translations for additional instance without blocking
383
+ // anything else in case of missing language
384
+ try {
385
+ // eslint-disable-next-line no-await-in-loop
386
+ await instances[i].fetchTranslations(localeCode);
387
+ } catch (e) {
388
+ // no-op
389
+ }
390
+ }
391
+ }
392
+ }
393
+ // Reloop through the instances to avoid content flash
394
+ instances.forEach((instance) => {
395
+ if (instance.getCurrentLocale() !== localeCode) {
396
+ // eslint-disable-next-line no-param-reassign
397
+ instance.currentLocale = localeCode;
398
+ sendEvent(LOCALE_CHANGED, localeCode, instance);
399
+ }
400
+ });
401
+ }
315
402
  }
@@ -11,7 +11,10 @@ export default class MemoryCache {
11
11
  * @param {String} translations[key] - Translation string
12
12
  */
13
13
  update(localeCode, translations) {
14
- this.translationsByLocale[localeCode] = translations;
14
+ if (!this.translationsByLocale[localeCode]) {
15
+ this.translationsByLocale[localeCode] = {};
16
+ }
17
+ Object.assign(this.translationsByLocale[localeCode], translations);
15
18
  }
16
19
 
17
20
  /**
package/src/index.d.ts CHANGED
@@ -6,4 +6,5 @@ declare module '@transifex/native' {
6
6
  export const SourceErrorPolicy: any;
7
7
  export const ThrowErrorPolicy: any;
8
8
  export const MessageFormatRenderer: any;
9
+ export const createNativeInstance: any;
9
10
  }
package/src/index.js CHANGED
@@ -7,6 +7,15 @@ import _SourceErrorPolicy from './policies/SourceErrorPolicy';
7
7
  import _ThrowErrorPolicy from './policies/ThrowErrorPolicy';
8
8
  import _MessageFormatRenderer from './renderers/MessageFormatRenderer';
9
9
 
10
+ function _createNativeInstance(initOptions) {
11
+ const instance = new TxNative();
12
+ instance.t = instance.translate.bind(instance);
13
+ if (initOptions) {
14
+ instance.init(initOptions);
15
+ }
16
+ return instance;
17
+ }
18
+
10
19
  export * from './utils';
11
20
  export * from './events';
12
21
 
@@ -15,6 +24,7 @@ export const SourceStringPolicy = _SourceStringPolicy;
15
24
  export const SourceErrorPolicy = _SourceErrorPolicy;
16
25
  export const ThrowErrorPolicy = _ThrowErrorPolicy;
17
26
  export const MessageFormatRenderer = _MessageFormatRenderer;
27
+ export const createNativeInstance = _createNativeInstance;
18
28
 
19
29
  export const tx = new TxNative();
20
30
  export const t = tx.translate.bind(tx);