@vocab/core 1.1.2 → 1.2.0

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/README.md CHANGED
@@ -422,20 +422,81 @@ Or to re-run the compiler when files change use:
422
422
  $ vocab compile --watch
423
423
  ```
424
424
 
425
- ## External translation tooling
425
+ ## External Translation Tooling
426
426
 
427
427
  Vocab can be used to synchronize your translations with translations from a remote translation platform.
428
428
 
429
- | Platform | Environment Variables |
430
- | -------------------------------------------- | ----------------------------------- |
431
- | [Phrase](https://developers.phrase.com/api/) | PHRASE_PROJECT_ID, PHRASE_API_TOKEN |
429
+ | Platform | Environment Variables |
430
+ | -------- | ----------------------------------- |
431
+ | [Phrase] | PHRASE_PROJECT_ID, PHRASE_API_TOKEN |
432
432
 
433
433
  ```bash
434
434
  $ vocab push --branch my-branch
435
- $ vocab push --branch my-branch --delete-unused-keys
436
435
  $ vocab pull --branch my-branch
437
436
  ```
438
437
 
438
+ ### [Phrase] Platform Features
439
+
440
+ #### Delete Unused keys
441
+
442
+ When uploading translations, Phrase identifies keys that exist in the Phrase project, but were not
443
+ referenced in the upload. These keys can be deleted from Phrase by providing the
444
+ `---delete-unused-keys` flag to `vocab push`. E.g.
445
+
446
+ ```sh
447
+ $ vocab push --branch my-branch --delete-unused-keys
448
+ ```
449
+
450
+ [phrase]: https://developers.phrase.com/api/
451
+
452
+ #### [Tags]
453
+
454
+ `vocab push` supports uploading [tags] to Phrase.
455
+
456
+ Tags can be added to an individual key via the `tags` property:
457
+
458
+ ```jsonc
459
+ // translations.json
460
+ {
461
+ "Hello": {
462
+ "message": "Hello",
463
+ "tags": ["greeting", "home_page"]
464
+ },
465
+ "Goodbye": {
466
+ "message": "Goodbye",
467
+ "tags": ["home_page"]
468
+ }
469
+ }
470
+ ```
471
+
472
+ Tags can also be added under a top-level `_meta` field. This will result in the tags applying to all
473
+ keys specified in the file:
474
+
475
+ ```jsonc
476
+ // translations.json
477
+ {
478
+ "_meta": {
479
+ "tags": ["home_page"]
480
+ },
481
+ "Hello": {
482
+ "message": "Hello",
483
+ "tags": ["greeting"]
484
+ },
485
+ "Goodbye": {
486
+ "message": "Goodbye"
487
+ }
488
+ }
489
+ ```
490
+
491
+ In the above example, both the `Hello` and `Goodbye` keys would have the `home_page` tag attached to
492
+ them, but only the `Hello` key would have the `usage_greeting` tag attached to it.
493
+
494
+ **NOTE**: Only tags specified on keys in your [`devLanguage`][configuration] will be uploaded.
495
+ Tags on keys in other languages will be ignored.
496
+
497
+ [tags]: https://support.phrase.com/hc/en-us/articles/5822598372252-Tags-Strings-
498
+ [configuration]: #Configuration
499
+
439
500
  ## Troubleshooting
440
501
 
441
502
  ### Problem: Passed locale is being ignored or using en-US instead
@@ -1,4 +1,4 @@
1
- import { TranslationsByKey, UserConfig, LoadedTranslation, LanguageTarget } from '@vocab/types';
1
+ import type { TranslationsByKey, UserConfig, LoadedTranslation, LanguageTarget } from '@vocab/types';
2
2
  import { Fallback } from './utils';
3
3
  export declare function getUniqueKey(key: string, namespace: string): string;
4
4
  export declare function mergeWithDevLanguageTranslation({ translation, devTranslation, }: {
@@ -20,11 +20,13 @@ export declare function loadAltLanguageFile({ filePath, languageName, devTransla
20
20
  devTranslation: TranslationsByKey;
21
21
  fallbacks: Fallback;
22
22
  }, { devLanguage, languages }: UserConfig): TranslationsByKey;
23
- export declare function loadTranslation({ filePath, fallbacks, }: {
23
+ export declare function loadTranslation({ filePath, fallbacks, withTags, }: {
24
24
  filePath: string;
25
25
  fallbacks: Fallback;
26
+ withTags?: boolean;
26
27
  }, userConfig: UserConfig): LoadedTranslation;
27
- export declare function loadAllTranslations({ fallbacks, includeNodeModules, }: {
28
+ export declare function loadAllTranslations({ fallbacks, includeNodeModules, withTags, }: {
28
29
  fallbacks: Fallback;
29
30
  includeNodeModules: boolean;
31
+ withTags?: boolean;
30
32
  }, config: UserConfig): Promise<Array<LoadedTranslation>>;
@@ -279,18 +279,20 @@ function printValidationError(...params) {
279
279
  console.error(chalk__default['default'].red('Error loading translation:'), ...params);
280
280
  }
281
281
 
282
- function getTranslationsFromFile(translations, {
282
+ function getTranslationsFromFile(translationFileContents, {
283
283
  isAltLanguage,
284
- filePath
284
+ filePath,
285
+ withTags
285
286
  }) {
286
- if (!translations || typeof translations !== 'object') {
287
- throw new Error(`Unable to read translation file ${filePath}. Translations must be an object`);
287
+ if (!translationFileContents || typeof translationFileContents !== 'object') {
288
+ throw new Error(`Unable to read translation file ${filePath}. Translations must be an object.`);
288
289
  }
289
290
 
290
291
  const {
291
292
  $namespace,
293
+ _meta,
292
294
  ...keys
293
- } = translations;
295
+ } = translationFileContents;
294
296
 
295
297
  if (isAltLanguage && $namespace) {
296
298
  printValidationError(`Found $namespace in alt language file in ${filePath}. $namespace is only used in the dev language and will be ignored.`);
@@ -300,9 +302,18 @@ function getTranslationsFromFile(translations, {
300
302
  printValidationError(`Found non-string $namespace in language file in ${filePath}. $namespace must be a string.`);
301
303
  }
302
304
 
305
+ if (isAltLanguage && _meta !== null && _meta !== void 0 && _meta.tags) {
306
+ printValidationError(`Found _meta.tags in alt language file in ${filePath}. _meta.tags is only used in the dev language and will be ignored.`);
307
+ } // Never return tags if we're fetching translations for an alt language
308
+
309
+
310
+ const includeTags = !isAltLanguage && withTags;
303
311
  const validKeys = {};
304
312
 
305
- for (const [translationKey, translation] of Object.entries(keys)) {
313
+ for (const [translationKey, {
314
+ tags,
315
+ ...translation
316
+ }] of Object.entries(keys)) {
306
317
  if (typeof translation === 'string') {
307
318
  printValidationError(`Found string for a translation "${translationKey}" in ${filePath}. Translation must be an object of the format {message: string}.`);
308
319
  continue;
@@ -318,12 +329,18 @@ function getTranslationsFromFile(translations, {
318
329
  continue;
319
330
  }
320
331
 
321
- validKeys[translationKey] = translation;
332
+ validKeys[translationKey] = { ...translation,
333
+ tags: includeTags ? tags : undefined
334
+ };
322
335
  }
323
336
 
337
+ const metadata = {
338
+ tags: includeTags ? _meta === null || _meta === void 0 ? void 0 : _meta.tags : undefined
339
+ };
324
340
  return {
325
341
  $namespace,
326
- keys: validKeys
342
+ keys: validKeys,
343
+ metadata
327
344
  };
328
345
  }
329
346
 
@@ -374,9 +391,18 @@ function loadAltLanguageFile({
374
391
 
375
392
  return altLanguageTranslation;
376
393
  }
394
+
395
+ function stripTagsFromTranslations(translations) {
396
+ return Object.fromEntries(Object.entries(translations).map(([key, {
397
+ tags,
398
+ ...rest
399
+ }]) => [key, rest]));
400
+ }
401
+
377
402
  function loadTranslation({
378
403
  filePath,
379
- fallbacks
404
+ fallbacks,
405
+ withTags
380
406
  }, userConfig) {
381
407
  trace(`Loading translation file in "${fallbacks}" fallback mode: "${filePath}"`);
382
408
  const languageSet = {};
@@ -387,21 +413,24 @@ function loadTranslation({
387
413
  const relativePath = path__default['default'].relative(userConfig.projectRoot || process.cwd(), filePath);
388
414
  const {
389
415
  $namespace,
390
- keys: devTranslation
416
+ keys: devTranslation,
417
+ metadata
391
418
  } = getTranslationsFromFile(translationContent, {
392
419
  filePath,
393
- isAltLanguage: false
420
+ isAltLanguage: false,
421
+ withTags
394
422
  });
395
423
  const namespace = typeof $namespace === 'string' ? $namespace : getNamespaceByFilePath(relativePath, userConfig);
396
424
  trace(`Found file ${filePath}. Using namespace ${namespace}`);
397
425
  languageSet[userConfig.devLanguage] = devTranslation;
426
+ const devTranslationNoTags = withTags ? stripTagsFromTranslations(devTranslation) : devTranslation;
398
427
  const altLanguages = getAltLanguages(userConfig);
399
428
 
400
429
  for (const languageName of altLanguages) {
401
430
  languageSet[languageName] = loadAltLanguageFile({
402
431
  filePath,
403
432
  languageName,
404
- devTranslation,
433
+ devTranslation: devTranslationNoTags,
405
434
  fallbacks
406
435
  }, userConfig);
407
436
  }
@@ -424,12 +453,14 @@ function loadTranslation({
424
453
  keys: Object.keys(devTranslation),
425
454
  namespace,
426
455
  relativePath,
427
- languages: languageSet
456
+ languages: languageSet,
457
+ metadata
428
458
  };
429
459
  }
430
460
  async function loadAllTranslations({
431
461
  fallbacks,
432
- includeNodeModules
462
+ includeNodeModules,
463
+ withTags
433
464
  }, config) {
434
465
  const {
435
466
  projectRoot,
@@ -443,7 +474,8 @@ async function loadAllTranslations({
443
474
  trace(`Found ${translationFiles.length} translation files`);
444
475
  const result = await Promise.all(translationFiles.map(filePath => loadTranslation({
445
476
  filePath,
446
- fallbacks
477
+ fallbacks,
478
+ withTags
447
479
  }, config)));
448
480
  const keys = new Set();
449
481
 
@@ -569,7 +601,7 @@ async function generateRuntime(loadedTranslation) {
569
601
  languages: loadedLanguages,
570
602
  filePath
571
603
  } = loadedTranslation;
572
- trace('Generating types for', loadedTranslation.filePath);
604
+ trace('Generating types for', filePath);
573
605
  const translationTypes = new Map();
574
606
  let imports = new Set();
575
607
 
@@ -629,7 +661,7 @@ function watch(config) {
629
661
 
630
662
  if (targetFile) {
631
663
  try {
632
- const loadedTranslation = await loadTranslation({
664
+ const loadedTranslation = loadTranslation({
633
665
  filePath: targetFile,
634
666
  fallbacks: 'all'
635
667
  }, config);
@@ -279,18 +279,20 @@ function printValidationError(...params) {
279
279
  console.error(chalk__default['default'].red('Error loading translation:'), ...params);
280
280
  }
281
281
 
282
- function getTranslationsFromFile(translations, {
282
+ function getTranslationsFromFile(translationFileContents, {
283
283
  isAltLanguage,
284
- filePath
284
+ filePath,
285
+ withTags
285
286
  }) {
286
- if (!translations || typeof translations !== 'object') {
287
- throw new Error(`Unable to read translation file ${filePath}. Translations must be an object`);
287
+ if (!translationFileContents || typeof translationFileContents !== 'object') {
288
+ throw new Error(`Unable to read translation file ${filePath}. Translations must be an object.`);
288
289
  }
289
290
 
290
291
  const {
291
292
  $namespace,
293
+ _meta,
292
294
  ...keys
293
- } = translations;
295
+ } = translationFileContents;
294
296
 
295
297
  if (isAltLanguage && $namespace) {
296
298
  printValidationError(`Found $namespace in alt language file in ${filePath}. $namespace is only used in the dev language and will be ignored.`);
@@ -300,9 +302,18 @@ function getTranslationsFromFile(translations, {
300
302
  printValidationError(`Found non-string $namespace in language file in ${filePath}. $namespace must be a string.`);
301
303
  }
302
304
 
305
+ if (isAltLanguage && _meta !== null && _meta !== void 0 && _meta.tags) {
306
+ printValidationError(`Found _meta.tags in alt language file in ${filePath}. _meta.tags is only used in the dev language and will be ignored.`);
307
+ } // Never return tags if we're fetching translations for an alt language
308
+
309
+
310
+ const includeTags = !isAltLanguage && withTags;
303
311
  const validKeys = {};
304
312
 
305
- for (const [translationKey, translation] of Object.entries(keys)) {
313
+ for (const [translationKey, {
314
+ tags,
315
+ ...translation
316
+ }] of Object.entries(keys)) {
306
317
  if (typeof translation === 'string') {
307
318
  printValidationError(`Found string for a translation "${translationKey}" in ${filePath}. Translation must be an object of the format {message: string}.`);
308
319
  continue;
@@ -318,12 +329,18 @@ function getTranslationsFromFile(translations, {
318
329
  continue;
319
330
  }
320
331
 
321
- validKeys[translationKey] = translation;
332
+ validKeys[translationKey] = { ...translation,
333
+ tags: includeTags ? tags : undefined
334
+ };
322
335
  }
323
336
 
337
+ const metadata = {
338
+ tags: includeTags ? _meta === null || _meta === void 0 ? void 0 : _meta.tags : undefined
339
+ };
324
340
  return {
325
341
  $namespace,
326
- keys: validKeys
342
+ keys: validKeys,
343
+ metadata
327
344
  };
328
345
  }
329
346
 
@@ -374,9 +391,18 @@ function loadAltLanguageFile({
374
391
 
375
392
  return altLanguageTranslation;
376
393
  }
394
+
395
+ function stripTagsFromTranslations(translations) {
396
+ return Object.fromEntries(Object.entries(translations).map(([key, {
397
+ tags,
398
+ ...rest
399
+ }]) => [key, rest]));
400
+ }
401
+
377
402
  function loadTranslation({
378
403
  filePath,
379
- fallbacks
404
+ fallbacks,
405
+ withTags
380
406
  }, userConfig) {
381
407
  trace(`Loading translation file in "${fallbacks}" fallback mode: "${filePath}"`);
382
408
  const languageSet = {};
@@ -387,21 +413,24 @@ function loadTranslation({
387
413
  const relativePath = path__default['default'].relative(userConfig.projectRoot || process.cwd(), filePath);
388
414
  const {
389
415
  $namespace,
390
- keys: devTranslation
416
+ keys: devTranslation,
417
+ metadata
391
418
  } = getTranslationsFromFile(translationContent, {
392
419
  filePath,
393
- isAltLanguage: false
420
+ isAltLanguage: false,
421
+ withTags
394
422
  });
395
423
  const namespace = typeof $namespace === 'string' ? $namespace : getNamespaceByFilePath(relativePath, userConfig);
396
424
  trace(`Found file ${filePath}. Using namespace ${namespace}`);
397
425
  languageSet[userConfig.devLanguage] = devTranslation;
426
+ const devTranslationNoTags = withTags ? stripTagsFromTranslations(devTranslation) : devTranslation;
398
427
  const altLanguages = getAltLanguages(userConfig);
399
428
 
400
429
  for (const languageName of altLanguages) {
401
430
  languageSet[languageName] = loadAltLanguageFile({
402
431
  filePath,
403
432
  languageName,
404
- devTranslation,
433
+ devTranslation: devTranslationNoTags,
405
434
  fallbacks
406
435
  }, userConfig);
407
436
  }
@@ -424,12 +453,14 @@ function loadTranslation({
424
453
  keys: Object.keys(devTranslation),
425
454
  namespace,
426
455
  relativePath,
427
- languages: languageSet
456
+ languages: languageSet,
457
+ metadata
428
458
  };
429
459
  }
430
460
  async function loadAllTranslations({
431
461
  fallbacks,
432
- includeNodeModules
462
+ includeNodeModules,
463
+ withTags
433
464
  }, config) {
434
465
  const {
435
466
  projectRoot,
@@ -443,7 +474,8 @@ async function loadAllTranslations({
443
474
  trace(`Found ${translationFiles.length} translation files`);
444
475
  const result = await Promise.all(translationFiles.map(filePath => loadTranslation({
445
476
  filePath,
446
- fallbacks
477
+ fallbacks,
478
+ withTags
447
479
  }, config)));
448
480
  const keys = new Set();
449
481
 
@@ -569,7 +601,7 @@ async function generateRuntime(loadedTranslation) {
569
601
  languages: loadedLanguages,
570
602
  filePath
571
603
  } = loadedTranslation;
572
- trace('Generating types for', loadedTranslation.filePath);
604
+ trace('Generating types for', filePath);
573
605
  const translationTypes = new Map();
574
606
  let imports = new Set();
575
607
 
@@ -629,7 +661,7 @@ function watch(config) {
629
661
 
630
662
  if (targetFile) {
631
663
  try {
632
- const loadedTranslation = await loadTranslation({
664
+ const loadedTranslation = loadTranslation({
633
665
  filePath: targetFile,
634
666
  fallbacks: 'all'
635
667
  }, config);
@@ -263,18 +263,20 @@ function printValidationError(...params) {
263
263
  console.error(chalk.red('Error loading translation:'), ...params);
264
264
  }
265
265
 
266
- function getTranslationsFromFile(translations, {
266
+ function getTranslationsFromFile(translationFileContents, {
267
267
  isAltLanguage,
268
- filePath
268
+ filePath,
269
+ withTags
269
270
  }) {
270
- if (!translations || typeof translations !== 'object') {
271
- throw new Error(`Unable to read translation file ${filePath}. Translations must be an object`);
271
+ if (!translationFileContents || typeof translationFileContents !== 'object') {
272
+ throw new Error(`Unable to read translation file ${filePath}. Translations must be an object.`);
272
273
  }
273
274
 
274
275
  const {
275
276
  $namespace,
277
+ _meta,
276
278
  ...keys
277
- } = translations;
279
+ } = translationFileContents;
278
280
 
279
281
  if (isAltLanguage && $namespace) {
280
282
  printValidationError(`Found $namespace in alt language file in ${filePath}. $namespace is only used in the dev language and will be ignored.`);
@@ -284,9 +286,18 @@ function getTranslationsFromFile(translations, {
284
286
  printValidationError(`Found non-string $namespace in language file in ${filePath}. $namespace must be a string.`);
285
287
  }
286
288
 
289
+ if (isAltLanguage && _meta !== null && _meta !== void 0 && _meta.tags) {
290
+ printValidationError(`Found _meta.tags in alt language file in ${filePath}. _meta.tags is only used in the dev language and will be ignored.`);
291
+ } // Never return tags if we're fetching translations for an alt language
292
+
293
+
294
+ const includeTags = !isAltLanguage && withTags;
287
295
  const validKeys = {};
288
296
 
289
- for (const [translationKey, translation] of Object.entries(keys)) {
297
+ for (const [translationKey, {
298
+ tags,
299
+ ...translation
300
+ }] of Object.entries(keys)) {
290
301
  if (typeof translation === 'string') {
291
302
  printValidationError(`Found string for a translation "${translationKey}" in ${filePath}. Translation must be an object of the format {message: string}.`);
292
303
  continue;
@@ -302,12 +313,18 @@ function getTranslationsFromFile(translations, {
302
313
  continue;
303
314
  }
304
315
 
305
- validKeys[translationKey] = translation;
316
+ validKeys[translationKey] = { ...translation,
317
+ tags: includeTags ? tags : undefined
318
+ };
306
319
  }
307
320
 
321
+ const metadata = {
322
+ tags: includeTags ? _meta === null || _meta === void 0 ? void 0 : _meta.tags : undefined
323
+ };
308
324
  return {
309
325
  $namespace,
310
- keys: validKeys
326
+ keys: validKeys,
327
+ metadata
311
328
  };
312
329
  }
313
330
 
@@ -358,9 +375,18 @@ function loadAltLanguageFile({
358
375
 
359
376
  return altLanguageTranslation;
360
377
  }
378
+
379
+ function stripTagsFromTranslations(translations) {
380
+ return Object.fromEntries(Object.entries(translations).map(([key, {
381
+ tags,
382
+ ...rest
383
+ }]) => [key, rest]));
384
+ }
385
+
361
386
  function loadTranslation({
362
387
  filePath,
363
- fallbacks
388
+ fallbacks,
389
+ withTags
364
390
  }, userConfig) {
365
391
  trace(`Loading translation file in "${fallbacks}" fallback mode: "${filePath}"`);
366
392
  const languageSet = {};
@@ -371,21 +397,24 @@ function loadTranslation({
371
397
  const relativePath = path.relative(userConfig.projectRoot || process.cwd(), filePath);
372
398
  const {
373
399
  $namespace,
374
- keys: devTranslation
400
+ keys: devTranslation,
401
+ metadata
375
402
  } = getTranslationsFromFile(translationContent, {
376
403
  filePath,
377
- isAltLanguage: false
404
+ isAltLanguage: false,
405
+ withTags
378
406
  });
379
407
  const namespace = typeof $namespace === 'string' ? $namespace : getNamespaceByFilePath(relativePath, userConfig);
380
408
  trace(`Found file ${filePath}. Using namespace ${namespace}`);
381
409
  languageSet[userConfig.devLanguage] = devTranslation;
410
+ const devTranslationNoTags = withTags ? stripTagsFromTranslations(devTranslation) : devTranslation;
382
411
  const altLanguages = getAltLanguages(userConfig);
383
412
 
384
413
  for (const languageName of altLanguages) {
385
414
  languageSet[languageName] = loadAltLanguageFile({
386
415
  filePath,
387
416
  languageName,
388
- devTranslation,
417
+ devTranslation: devTranslationNoTags,
389
418
  fallbacks
390
419
  }, userConfig);
391
420
  }
@@ -408,12 +437,14 @@ function loadTranslation({
408
437
  keys: Object.keys(devTranslation),
409
438
  namespace,
410
439
  relativePath,
411
- languages: languageSet
440
+ languages: languageSet,
441
+ metadata
412
442
  };
413
443
  }
414
444
  async function loadAllTranslations({
415
445
  fallbacks,
416
- includeNodeModules
446
+ includeNodeModules,
447
+ withTags
417
448
  }, config) {
418
449
  const {
419
450
  projectRoot,
@@ -427,7 +458,8 @@ async function loadAllTranslations({
427
458
  trace(`Found ${translationFiles.length} translation files`);
428
459
  const result = await Promise.all(translationFiles.map(filePath => loadTranslation({
429
460
  filePath,
430
- fallbacks
461
+ fallbacks,
462
+ withTags
431
463
  }, config)));
432
464
  const keys = new Set();
433
465
 
@@ -553,7 +585,7 @@ async function generateRuntime(loadedTranslation) {
553
585
  languages: loadedLanguages,
554
586
  filePath
555
587
  } = loadedTranslation;
556
- trace('Generating types for', loadedTranslation.filePath);
588
+ trace('Generating types for', filePath);
557
589
  const translationTypes = new Map();
558
590
  let imports = new Set();
559
591
 
@@ -613,7 +645,7 @@ function watch(config) {
613
645
 
614
646
  if (targetFile) {
615
647
  try {
616
- const loadedTranslation = await loadTranslation({
648
+ const loadedTranslation = loadTranslation({
617
649
  filePath: targetFile,
618
650
  fallbacks: 'all'
619
651
  }, config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vocab/core",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "main": "dist/vocab-core.cjs.js",
5
5
  "module": "dist/vocab-core.esm.js",
6
6
  "exports": {
@@ -40,7 +40,7 @@
40
40
  ],
41
41
  "dependencies": {
42
42
  "@formatjs/icu-messageformat-parser": "^2.0.10",
43
- "@vocab/types": "^1.1.1",
43
+ "@vocab/types": "^1.1.2",
44
44
  "chalk": "^4.1.0",
45
45
  "chokidar": "^3.4.3",
46
46
  "debug": "^4.3.1",
package/CHANGELOG.md DELETED
@@ -1,204 +0,0 @@
1
- # @vocab/core
2
-
3
- ## 1.1.2
4
-
5
- ### Patch Changes
6
-
7
- - [`e5a066c`](https://github.com/seek-oss/vocab/commit/e5a066c8a7539a62a9c1c4d813aa87461ba43cdc) [#96](https://github.com/seek-oss/vocab/pull/96) Thanks [@askoufis](https://github.com/askoufis)! - Update `intl-messageformat` dependencies
8
-
9
- - Updated dependencies [[`e5a066c`](https://github.com/seek-oss/vocab/commit/e5a066c8a7539a62a9c1c4d813aa87461ba43cdc)]:
10
- - @vocab/types@1.1.1
11
-
12
- ## 1.1.1
13
-
14
- ### Patch Changes
15
-
16
- - [`09a698a`](https://github.com/seek-oss/vocab/commit/09a698af6aff86a851e4f829916b8f1f6beaca58) [#89](https://github.com/seek-oss/vocab/pull/89) Thanks [@mikebarkmin](https://github.com/mikebarkmin)! - Add exports to packages with multiple entry points. This fixes
17
- `ERR_UNSUPPORTED_DIR_IMPORT` issues e.g. with NextJS or other setups, which
18
- rely on the new node resolver when using ESM packages.
19
-
20
- ## 1.1.0
21
-
22
- ### Minor Changes
23
-
24
- - [`87333d7`](https://github.com/seek-oss/vocab/commit/87333d79c4a883b07d7d8f2c272b16e2243c49bd) [#80](https://github.com/seek-oss/vocab/pull/80) Thanks [@askoufis](https://github.com/askoufis)! - Enable the creation of generated languages via the `generatedLanguages` config.
25
- See [the docs] for more information and examples.
26
-
27
- [the docs]: https://github.com/seek-oss/vocab#generated-languages
28
-
29
- ### Patch Changes
30
-
31
- - Updated dependencies [[`87333d7`](https://github.com/seek-oss/vocab/commit/87333d79c4a883b07d7d8f2c272b16e2243c49bd)]:
32
- - @vocab/types@1.1.0
33
-
34
- ## 1.0.4
35
-
36
- ### Patch Changes
37
-
38
- - [`206c0fa`](https://github.com/seek-oss/vocab/commit/206c0fa36b05f23da593ebed801197c523477af6) [#78](https://github.com/seek-oss/vocab/pull/78) Thanks [@askoufis](https://github.com/askoufis)! - Fix incorrect language hierarchy when an extended language extends another language
39
-
40
- ## 1.0.3
41
-
42
- ### Patch Changes
43
-
44
- - [`78e874f`](https://github.com/seek-oss/vocab/commit/78e874f720ca34d771072c09fe55b57ff3158e02) [#71](https://github.com/seek-oss/vocab/pull/71) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Only write compiled runtime files to disk if they have been changed
45
-
46
- ## 1.0.2
47
-
48
- ### Patch Changes
49
-
50
- - [`3ec6dba`](https://github.com/seek-oss/vocab/commit/3ec6dbaad590299cc33e2d9d4a877576eb05853a) [#63](https://github.com/seek-oss/vocab/pull/63) Thanks [@jahredhope](https://github.com/jahredhope)! - Migrate to new @formatjs/icu-messageformat-parser as intl-messageformat-parser has been deprecated
51
-
52
- - Updated dependencies [[`3ec6dba`](https://github.com/seek-oss/vocab/commit/3ec6dbaad590299cc33e2d9d4a877576eb05853a)]:
53
- - @vocab/types@1.0.1
54
-
55
- ## 1.0.1
56
-
57
- ### Patch Changes
58
-
59
- - [`c9a38dd`](https://github.com/seek-oss/vocab/commit/c9a38dd15e2c2a47fc4d5eb2348fdd08a6982768) [#54](https://github.com/seek-oss/vocab/pull/54) Thanks [@jahredhope](https://github.com/jahredhope)! - Allow special characters within translation keys and messages
60
-
61
- ## 1.0.0
62
-
63
- ### Major Changes
64
-
65
- - [`3031054`](https://github.com/seek-oss/vocab/commit/303105440851db6126f0606e1607745b27dd981c) [#51](https://github.com/seek-oss/vocab/pull/51) Thanks [@jahredhope](https://github.com/jahredhope)! - Release v1.0.0
66
-
67
- Release Vocab as v1.0.0 to signify a stable API and support future [semver versioning](https://semver.org/) releases.
68
-
69
- Vocab has seen a lot of iteration and changes since it was first published on 20 November 2020. We are now confident with the API and believe Vocab is ready for common use.
70
-
71
- ### Patch Changes
72
-
73
- - [`0074382`](https://github.com/seek-oss/vocab/commit/007438273ef70f5d5ded45777933651ad8df36f6) [#52](https://github.com/seek-oss/vocab/pull/52) Thanks [@jahredhope](https://github.com/jahredhope)! - Remove React dependency on core types.
74
-
75
- Direct use of tags in Translations now have stricter type definitions.
76
-
77
- - Updated dependencies [[`0074382`](https://github.com/seek-oss/vocab/commit/007438273ef70f5d5ded45777933651ad8df36f6), [`3031054`](https://github.com/seek-oss/vocab/commit/303105440851db6126f0606e1607745b27dd981c)]:
78
- - @vocab/types@1.0.0
79
-
80
- ## 0.0.11
81
-
82
- ### Patch Changes
83
-
84
- - [`5b1fdc0`](https://github.com/seek-oss/vocab/commit/5b1fdc019522b12e7ef94b2fec57b54a9310d41c) [#46](https://github.com/seek-oss/vocab/pull/46) Thanks [@jahredhope](https://github.com/jahredhope)! - Enable the use of translation files directly with 3 new documented methods for working with translations.
85
-
86
- ```typescript
87
- /**
88
- * Retrieve messages. If not available, will attempt to load messages and resolve once complete.
89
- */
90
- translations.getMessages(language);
91
- /**
92
- * Retrieve already loaded messages. Will return null if messages haven't been loaded.
93
- */
94
- translations.getLoadedMessages(language);
95
- /**
96
- * Load messages for the given language. Resolving once complete.
97
- */
98
- translations.load(language);
99
- ```
100
-
101
- - Updated dependencies [[`5b1fdc0`](https://github.com/seek-oss/vocab/commit/5b1fdc019522b12e7ef94b2fec57b54a9310d41c)]:
102
- - @vocab/types@0.0.9
103
-
104
- ## 0.0.10
105
-
106
- ### Patch Changes
107
-
108
- - [`7c96a14`](https://github.com/seek-oss/vocab/commit/7c96a142f602132d38c1df1a47a1f4657dc5c94c) [#43](https://github.com/seek-oss/vocab/pull/43) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Return `NonNullable<ReactNode>` instead of `ReactNode` from translation function
109
-
110
- ## 0.0.9
111
-
112
- ### Patch Changes
113
-
114
- - [`3034bd3`](https://github.com/seek-oss/vocab/commit/3034bd3de610a9d1f3bfbd8caefa27064dee2710) [#40](https://github.com/seek-oss/vocab/pull/40) Thanks [@jahredhope](https://github.com/jahredhope)! - Fix .vocab files with no prefix not compiling
115
-
116
- * [`c110745`](https://github.com/seek-oss/vocab/commit/c110745b79df1a8ade6b1d8a49e798b04a7b95e1) [#42](https://github.com/seek-oss/vocab/pull/42) Thanks [@jahredhope](https://github.com/jahredhope)! - Avoid overriding existing translations files for new directories
117
-
118
- ## 0.0.8
119
-
120
- ### Patch Changes
121
-
122
- - [`f2fca67`](https://github.com/seek-oss/vocab/commit/f2fca679c66ae65405a0aa24f0a0e472026aad0d) [#36](https://github.com/seek-oss/vocab/pull/36) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Support custom locales for ICU message parsing
123
-
124
- - Updated dependencies [[`f2fca67`](https://github.com/seek-oss/vocab/commit/f2fca679c66ae65405a0aa24f0a0e472026aad0d)]:
125
- - @vocab/types@0.0.8
126
-
127
- ## 0.0.7
128
-
129
- ### Patch Changes
130
-
131
- - [`283bcad`](https://github.com/seek-oss/vocab/commit/283bcada06e622ab14ed891743ed3f55cf09e245) [#33](https://github.com/seek-oss/vocab/pull/33) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Move all vocab files to single directory with configurable suffix
132
-
133
- * [`ad0d240`](https://github.com/seek-oss/vocab/commit/ad0d2404545ded8e11621eae8f29467ff3352366) [#31](https://github.com/seek-oss/vocab/pull/31) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Move the node runtime from @vocab/webpack to @vocab/core
134
-
135
- - [`f3992ef`](https://github.com/seek-oss/vocab/commit/f3992efbf08939ebf853fac650a49cc46dc51dfb) [#34](https://github.com/seek-oss/vocab/pull/34) Thanks [@jahredhope](https://github.com/jahredhope)! - Create translation files for newly created vocab directories
136
-
137
- * [`f3992ef`](https://github.com/seek-oss/vocab/commit/f3992efbf08939ebf853fac650a49cc46dc51dfb) [#34](https://github.com/seek-oss/vocab/pull/34) Thanks [@jahredhope](https://github.com/jahredhope)! - Validate translation files as loaded. Providing additional error messaging.
138
-
139
- * Updated dependencies [[`283bcad`](https://github.com/seek-oss/vocab/commit/283bcada06e622ab14ed891743ed3f55cf09e245), [`f3992ef`](https://github.com/seek-oss/vocab/commit/f3992efbf08939ebf853fac650a49cc46dc51dfb)]:
140
- - @vocab/types@0.0.7
141
-
142
- ## 0.0.6
143
-
144
- ### Patch Changes
145
-
146
- - [`80a46c0`](https://github.com/seek-oss/vocab/commit/80a46c01a55408675f5822c3618519f80136c3ab) [#27](https://github.com/seek-oss/vocab/pull/27) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Add `ignore` config for ignoring files/folders from cli scripts
147
-
148
- * [`80a46c0`](https://github.com/seek-oss/vocab/commit/80a46c01a55408675f5822c3618519f80136c3ab) [#27](https://github.com/seek-oss/vocab/pull/27) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Ignore node_modules from push, pull and compile scripts
149
-
150
- * Updated dependencies [[`80a46c0`](https://github.com/seek-oss/vocab/commit/80a46c01a55408675f5822c3618519f80136c3ab)]:
151
- - @vocab/types@0.0.6
152
-
153
- ## 0.0.5
154
-
155
- ### Patch Changes
156
-
157
- - [`371ed16`](https://github.com/seek-oss/vocab/commit/371ed16a232a04dab13afa7e2b352dfb6724eea4) [#25](https://github.com/seek-oss/vocab/pull/25) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Watch alt language files as well as dev language
158
-
159
- * [`c222d68`](https://github.com/seek-oss/vocab/commit/c222d68a3c0c24723a338eccb959798881f6a118) [#24](https://github.com/seek-oss/vocab/pull/24) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Changed glob constants to functions
160
-
161
- ## 0.0.4
162
-
163
- ### Patch Changes
164
-
165
- - [`5f5c581`](https://github.com/seek-oss/vocab/commit/5f5c581a65bff28729ee19e1ec0bdea488a9d6c2) [#19](https://github.com/seek-oss/vocab/pull/19) Thanks [@jahredhope](https://github.com/jahredhope)! - Compile useable TypeScript importable files with `vocab compile`.
166
-
167
- The new `vocab compile` step replaces `vocab generate-types` in creating a fully functional **translations.ts** file.
168
-
169
- This allows vocab to be used **without the Webpack Plugin**, however use of the plugin is still heavily advised to ensure optimal loading of translation content on the web.
170
-
171
- Support for unit testing is now better than ever! The newly created **translations.ts** means your unit test code will see the same code as available while rendering.
172
-
173
- See the [documentation](https://github.com/seek-oss/vocab) for further usage details.
174
-
175
- * [`02f943c`](https://github.com/seek-oss/vocab/commit/02f943ca892913b41f9e4720a72400777cf14b3d) [#17](https://github.com/seek-oss/vocab/pull/17) Thanks [@jahredhope](https://github.com/jahredhope)! - Add additional debug traces
176
-
177
- * Updated dependencies [[`5f5c581`](https://github.com/seek-oss/vocab/commit/5f5c581a65bff28729ee19e1ec0bdea488a9d6c2)]:
178
- - @vocab/types@0.0.5
179
-
180
- ## 0.0.3
181
-
182
- ### Patch Changes
183
-
184
- - [`08de30d`](https://github.com/seek-oss/vocab/commit/08de30d338c2a5ebdcf14da7c736dddf22e7ca9e) [#14](https://github.com/seek-oss/vocab/pull/14) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Add ability to override files namespace with \$namespace
185
-
186
- * [`ed6cf40`](https://github.com/seek-oss/vocab/commit/ed6cf408973f2e9c4d07a71fcb52f40294ebaf65) [#13](https://github.com/seek-oss/vocab/pull/13) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Add validation script for identifying missing keys
187
-
188
- - [`26b52f4`](https://github.com/seek-oss/vocab/commit/26b52f4878ded440841e08c858bdc9e685500c2a) [#16](https://github.com/seek-oss/vocab/pull/16) Thanks [@jahredhope](https://github.com/jahredhope)! - Enable debugging with DEBUG environment variable
189
-
190
- * [`b5a5a05`](https://github.com/seek-oss/vocab/commit/b5a5a05a5bb87b48e6e9160af75f555728143ea2) [#15](https://github.com/seek-oss/vocab/pull/15) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Added watch mode to generate-types
191
-
192
- * Updated dependencies [[`08de30d`](https://github.com/seek-oss/vocab/commit/08de30d338c2a5ebdcf14da7c736dddf22e7ca9e)]:
193
- - @vocab/types@0.0.4
194
-
195
- ## 0.0.2
196
-
197
- ### Patch Changes
198
-
199
- - [`4710f34`](https://github.com/seek-oss/vocab/commit/4710f341f2827643e3eff69ef7e26d44ec6e8a2b) [#8](https://github.com/seek-oss/vocab/pull/8) Thanks [@mattcompiles](https://github.com/mattcompiles)! - Infer `t` return type more intelligently
200
-
201
- The translate key function (`t`) will now infer the return type as ReactNode only when the tag syntax is used.
202
-
203
- - Updated dependencies [[`4710f34`](https://github.com/seek-oss/vocab/commit/4710f341f2827643e3eff69ef7e26d44ec6e8a2b)]:
204
- - @vocab/types@0.0.3