@vocab/phrase 0.0.0-delete-unused-keys-20228144520 → 0.0.0-global-key-support-20231025223328

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.
@@ -5,6 +5,7 @@ import FormData from 'form-data';
5
5
  import fetch from 'node-fetch';
6
6
  import chalk from 'chalk';
7
7
  import debug from 'debug';
8
+ import { stringify } from 'csv-stringify/sync';
8
9
 
9
10
  const mkdir = promises.mkdir;
10
11
  const writeFile = promises.writeFile;
@@ -15,14 +16,59 @@ const log = (...params) => {
15
16
  console.log(chalk.yellow('Vocab'), ...params);
16
17
  };
17
18
 
19
+ function translationsToCsv(translations, devLanguage) {
20
+ const languages = Object.keys(translations);
21
+ const altLanguages = languages.filter(language => language !== devLanguage);
22
+ const devLanguageTranslations = translations[devLanguage];
23
+ const csvFilesByLanguage = Object.fromEntries(languages.map(language => [language, []]));
24
+ Object.entries(devLanguageTranslations).map(([key, {
25
+ message,
26
+ description,
27
+ tags
28
+ }]) => {
29
+ const sharedData = [key, description, tags === null || tags === void 0 ? void 0 : tags.join(',')];
30
+ const devLanguageRow = [...sharedData, message];
31
+ csvFilesByLanguage[devLanguage].push(devLanguageRow);
32
+ altLanguages.map(language => {
33
+ var _translations$languag, _translations$languag2;
34
+ const altTranslationMessage = (_translations$languag = translations[language]) === null || _translations$languag === void 0 ? void 0 : (_translations$languag2 = _translations$languag[key]) === null || _translations$languag2 === void 0 ? void 0 : _translations$languag2.message;
35
+ if (altTranslationMessage) {
36
+ csvFilesByLanguage[language].push([...sharedData, altTranslationMessage]);
37
+ }
38
+ });
39
+ });
40
+ const csvFileStrings = Object.fromEntries(Object.entries(csvFilesByLanguage)
41
+ // Ensure CSV files are only created if the language has at least 1 translation
42
+ .filter(([_, csvFile]) => csvFile.length > 0).map(([language, csvFile]) => {
43
+ const csvFileString = stringify(csvFile, {
44
+ delimiter: ',',
45
+ header: false
46
+ });
47
+ return [language, csvFileString];
48
+ }));
49
+
50
+ // Column indices start at 1
51
+ const keyIndex = 1;
52
+ const commentIndex = keyIndex + 1;
53
+ const tagColumn = commentIndex + 1;
54
+ const messageIndex = tagColumn + 1;
55
+ return {
56
+ csvFileStrings,
57
+ keyIndex,
58
+ messageIndex,
59
+ commentIndex,
60
+ tagColumn
61
+ };
62
+ }
63
+
64
+ /* eslint-disable no-console */
18
65
  function _callPhrase(path, options = {}) {
19
66
  const phraseApiToken = process.env.PHRASE_API_TOKEN;
20
-
21
67
  if (!phraseApiToken) {
22
68
  throw new Error('Missing PHRASE_API_TOKEN');
23
69
  }
24
-
25
- return fetch(path, { ...options,
70
+ return fetch(path, {
71
+ ...options,
26
72
  headers: {
27
73
  Authorization: `token ${phraseApiToken}`,
28
74
  // Provide identification via User Agent as requested in https://developers.phrase.com/api/#overview--identification-via-user-agent
@@ -31,30 +77,26 @@ function _callPhrase(path, options = {}) {
31
77
  }
32
78
  }).then(async response => {
33
79
  console.log(`${path}: ${response.status} - ${response.statusText}`);
34
- console.log(`Rate Limit: ${response.headers.get('X-Rate-Limit-Remaining')} of ${response.headers.get('X-Rate-Limit-Limit')} remaining. (${response.headers.get('X-Rate-Limit-Reset')} seconds remaining})`);
35
- console.log('\nLink:', response.headers.get('Link'), '\n'); // Print All Headers:
80
+ const secondsUntilLimitReset = Math.ceil(Number.parseFloat(response.headers.get('X-Rate-Limit-Reset') || '0') - Date.now() / 1000);
81
+ console.log(`Rate Limit: ${response.headers.get('X-Rate-Limit-Remaining')} of ${response.headers.get('X-Rate-Limit-Limit')} remaining. (${secondsUntilLimitReset} seconds remaining)`);
82
+ trace('\nLink:', response.headers.get('Link'), '\n');
83
+ // Print All Headers:
36
84
  // console.log(Array.from(r.headers.entries()));
37
85
 
38
86
  try {
39
87
  var _response$headers$get;
40
-
41
88
  const result = await response.json();
42
- console.log(`Internal Result (Length: ${result.length})\n`);
43
-
89
+ trace(`Internal Result (Length: ${result.length})\n`);
44
90
  if ((!options.method || options.method === 'GET') && (_response$headers$get = response.headers.get('Link')) !== null && _response$headers$get !== void 0 && _response$headers$get.includes('rel=next')) {
45
91
  var _response$headers$get2, _response$headers$get3;
46
-
47
92
  const [, nextPageUrl] = (_response$headers$get2 = (_response$headers$get3 = response.headers.get('Link')) === null || _response$headers$get3 === void 0 ? void 0 : _response$headers$get3.match(/<([^>]*)>; rel=next/)) !== null && _response$headers$get2 !== void 0 ? _response$headers$get2 : [];
48
-
49
93
  if (!nextPageUrl) {
50
- throw new Error('Cant parse next page URL');
94
+ throw new Error("Can't parse next page URL");
51
95
  }
52
-
53
- console.log('Results recieved with next page: ', nextPageUrl);
96
+ console.log('Results received with next page: ', nextPageUrl);
54
97
  const nextPageResult = await _callPhrase(nextPageUrl, options);
55
98
  return [...result, ...nextPageResult];
56
99
  }
57
-
58
100
  return result;
59
101
  } catch (e) {
60
102
  console.error('Unable to parse response as JSON', e);
@@ -62,19 +104,15 @@ function _callPhrase(path, options = {}) {
62
104
  }
63
105
  });
64
106
  }
65
-
66
107
  async function callPhrase(relativePath, options = {}) {
67
108
  const projectId = process.env.PHRASE_PROJECT_ID;
68
-
69
109
  if (!projectId) {
70
110
  throw new Error('Missing PHRASE_PROJECT_ID');
71
111
  }
72
-
73
112
  return _callPhrase(`https://api.phrase.com/v2/projects/${projectId}/${relativePath}`, options).then(result => {
74
113
  if (Array.isArray(result)) {
75
114
  console.log('Result length:', result.length);
76
115
  }
77
-
78
116
  return result;
79
117
  }).catch(error => {
80
118
  console.error(`Error calling phrase for ${relativePath}:`, error);
@@ -84,57 +122,81 @@ async function callPhrase(relativePath, options = {}) {
84
122
  async function pullAllTranslations(branch) {
85
123
  const phraseResult = await callPhrase(`translations?branch=${branch}&per_page=100`);
86
124
  const translations = {};
87
-
88
125
  for (const r of phraseResult) {
89
126
  if (!translations[r.locale.code]) {
90
127
  translations[r.locale.code] = {};
91
128
  }
92
-
93
129
  translations[r.locale.code][r.key.name] = {
94
130
  message: r.content
95
131
  };
96
132
  }
97
-
98
133
  return translations;
99
134
  }
100
- async function pushTranslationsByLocale(contents, locale, branch) {
101
- const formData = new FormData();
102
- const fileContents = Buffer.from(JSON.stringify(contents));
103
- formData.append('file', fileContents, {
104
- contentType: 'application/json',
105
- filename: `${locale}.json`
106
- });
107
- formData.append('file_format', 'json');
108
- formData.append('locale_id', locale);
109
- formData.append('branch', branch);
110
- formData.append('update_translations', 'true');
111
- trace('Starting to upload:', locale);
135
+ async function pushTranslations(translationsByLanguage, {
136
+ devLanguage,
137
+ branch
138
+ }) {
112
139
  const {
113
- id
114
- } = await callPhrase(`uploads`, {
115
- method: 'POST',
116
- body: formData
117
- });
118
- log('Upload ID:', id, '\n');
119
- log('Successfully Uploaded:', locale, '\n');
140
+ csvFileStrings,
141
+ keyIndex,
142
+ commentIndex,
143
+ tagColumn,
144
+ messageIndex
145
+ } = translationsToCsv(translationsByLanguage, devLanguage);
146
+ let devLanguageUploadId = '';
147
+ for (const [language, csvFileString] of Object.entries(csvFileStrings)) {
148
+ const formData = new FormData();
149
+ const fileContents = Buffer.from(csvFileString);
150
+ formData.append('file', fileContents, {
151
+ contentType: 'text/csv',
152
+ filename: `${language}.translations.csv`
153
+ });
154
+ formData.append('file_format', 'csv');
155
+ formData.append('branch', branch);
156
+ formData.append('update_translations', 'true');
157
+ formData.append('update_descriptions', 'true');
158
+ formData.append(`locale_mapping[${language}]`, messageIndex);
159
+ formData.append('format_options[key_index]', keyIndex);
160
+ formData.append('format_options[comment_index]', commentIndex);
161
+ formData.append('format_options[tag_column]', tagColumn);
162
+ formData.append('format_options[enable_pluralization]', 'false');
163
+ log(`Uploading translations for language ${language}`);
164
+ const result = await callPhrase(`uploads`, {
165
+ method: 'POST',
166
+ body: formData
167
+ });
168
+ trace('Upload result:\n', result);
169
+ if (result && 'id' in result) {
170
+ log('Upload ID:', result.id, '\n');
171
+ log('Successfully Uploaded\n');
172
+ } else {
173
+ log(`Error uploading: ${result === null || result === void 0 ? void 0 : result.message}\n`);
174
+ log('Response:', result);
175
+ throw new Error('Error uploading');
176
+ }
177
+ if (language === devLanguage) {
178
+ devLanguageUploadId = result.id;
179
+ }
180
+ }
120
181
  return {
121
- uploadId: id
182
+ devLanguageUploadId
122
183
  };
123
184
  }
124
- async function deleteUnusedKeys(uploadId, locale, branch) {
185
+ async function deleteUnusedKeys(uploadId, branch) {
125
186
  const query = `unmentioned_in_upload:${uploadId}`;
126
- const result = await callPhrase('keys', {
187
+ const {
188
+ records_affected
189
+ } = await callPhrase('keys', {
127
190
  method: 'DELETE',
128
191
  headers: {
129
192
  'Content-Type': 'application/json'
130
193
  },
131
194
  body: JSON.stringify({
132
195
  branch,
133
- locale_id: locale,
134
196
  q: query
135
197
  })
136
198
  });
137
- log('Successfully deleted', result.records_affected, 'unused keys from branch', branch);
199
+ log('Successfully deleted', records_affected, 'unused keys from branch', branch);
138
200
  }
139
201
  async function ensureBranch(branch) {
140
202
  await callPhrase(`branches`, {
@@ -146,63 +208,72 @@ async function ensureBranch(branch) {
146
208
  name: branch
147
209
  })
148
210
  });
149
- trace('Created branch:', branch);
211
+ log('Created branch:', branch);
150
212
  }
151
213
 
152
214
  async function pull({
153
- branch = 'local-development'
215
+ branch = 'local-development',
216
+ errorOnNoGlobalKeyTranslation
154
217
  }, config) {
155
218
  trace(`Pulling translations from branch ${branch}`);
156
219
  await ensureBranch(branch);
157
220
  const alternativeLanguages = getAltLanguages(config);
158
221
  const allPhraseTranslations = await pullAllTranslations(branch);
159
222
  trace(`Pulling translations from Phrase for languages ${config.devLanguage} and ${alternativeLanguages.join(', ')}`);
223
+ const phraseLanguages = Object.keys(allPhraseTranslations);
224
+ trace(`Found Phrase translations for languages ${phraseLanguages.join(', ')}`);
225
+ if (!phraseLanguages.includes(config.devLanguage)) {
226
+ throw new Error(`Phrase did not return any translations for the configured development language "${config.devLanguage}".\nPlease ensure this language is present in your Phrase project's configuration.`);
227
+ }
160
228
  const allVocabTranslations = await loadAllTranslations({
161
229
  fallbacks: 'none',
162
- includeNodeModules: false
230
+ includeNodeModules: false,
231
+ withTags: true
163
232
  }, config);
164
-
165
233
  for (const loadedTranslation of allVocabTranslations) {
166
234
  const devTranslations = loadedTranslation.languages[config.devLanguage];
167
-
168
235
  if (!devTranslations) {
169
236
  throw new Error('No dev language translations loaded');
170
237
  }
171
-
172
- const defaultValues = { ...devTranslations
238
+ const defaultValues = {
239
+ ...devTranslations
173
240
  };
174
241
  const localKeys = Object.keys(defaultValues);
175
-
176
242
  for (const key of localKeys) {
177
- defaultValues[key] = { ...defaultValues[key],
178
- ...allPhraseTranslations[config.devLanguage][getUniqueKey(key, loadedTranslation.namespace)]
243
+ var _defaultValues$key$gl;
244
+ defaultValues[key] = {
245
+ ...defaultValues[key],
246
+ ...allPhraseTranslations[config.devLanguage][(_defaultValues$key$gl = defaultValues[key].globalKey) !== null && _defaultValues$key$gl !== void 0 ? _defaultValues$key$gl : getUniqueKey(key, loadedTranslation.namespace)]
179
247
  };
180
248
  }
181
249
 
250
+ // Only write a `_meta` field if necessary
251
+ if (Object.keys(loadedTranslation.metadata).length > 0) {
252
+ defaultValues._meta = loadedTranslation.metadata;
253
+ }
182
254
  await writeFile(loadedTranslation.filePath, `${JSON.stringify(defaultValues, null, 2)}\n`);
183
-
184
255
  for (const alternativeLanguage of alternativeLanguages) {
185
256
  if (alternativeLanguage in allPhraseTranslations) {
186
- const altTranslations = { ...loadedTranslation.languages[alternativeLanguage]
257
+ const altTranslations = {
258
+ ...loadedTranslation.languages[alternativeLanguage]
187
259
  };
188
260
  const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
189
-
190
261
  for (const key of localKeys) {
191
- var _phraseAltTranslation;
192
-
193
- const phraseKey = getUniqueKey(key, loadedTranslation.namespace);
262
+ var _defaultValues$key$gl2, _phraseAltTranslation;
263
+ const phraseKey = (_defaultValues$key$gl2 = defaultValues[key].globalKey) !== null && _defaultValues$key$gl2 !== void 0 ? _defaultValues$key$gl2 : getUniqueKey(key, loadedTranslation.namespace);
194
264
  const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
195
-
196
265
  if (!phraseTranslationMessage) {
197
266
  trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
267
+ if (errorOnNoGlobalKeyTranslation && defaultValues[key].globalKey) {
268
+ throw new Error(`Missing translation for global key ${key} in language ${alternativeLanguage}`);
269
+ }
198
270
  continue;
199
271
  }
200
-
201
- altTranslations[key] = { ...altTranslations[key],
272
+ altTranslations[key] = {
273
+ ...altTranslations[key],
202
274
  message: phraseTranslationMessage
203
275
  };
204
276
  }
205
-
206
277
  const altTranslationFilePath = getAltLanguageFilePath(loadedTranslation.filePath, alternativeLanguage);
207
278
  await mkdir(path.dirname(altTranslationFilePath), {
208
279
  recursive: true
@@ -214,7 +285,8 @@ async function pull({
214
285
  }
215
286
 
216
287
  /**
217
- * Uploading to the Phrase API for each language. Adding a unique namespace to each key using file path they key came from
288
+ * Uploads translations to the Phrase API for each language.
289
+ * A unique namespace is appended to each key using the file path the key came from.
218
290
  */
219
291
  async function push({
220
292
  branch,
@@ -222,43 +294,54 @@ async function push({
222
294
  }, config) {
223
295
  const allLanguageTranslations = await loadAllTranslations({
224
296
  fallbacks: 'none',
225
- includeNodeModules: false
297
+ includeNodeModules: false,
298
+ withTags: true
226
299
  }, config);
227
300
  trace(`Pushing translations to branch ${branch}`);
228
301
  const allLanguages = config.languages.map(v => v.name);
229
302
  await ensureBranch(branch);
230
303
  trace(`Pushing translations to phrase for languages ${allLanguages.join(', ')}`);
231
304
  const phraseTranslations = {};
232
-
233
305
  for (const loadedTranslation of allLanguageTranslations) {
234
306
  for (const language of allLanguages) {
235
307
  const localTranslations = loadedTranslation.languages[language];
236
-
237
308
  if (!localTranslations) {
238
309
  continue;
239
310
  }
240
-
241
311
  if (!phraseTranslations[language]) {
242
312
  phraseTranslations[language] = {};
243
313
  }
244
-
314
+ const {
315
+ metadata: {
316
+ tags: sharedTags = []
317
+ }
318
+ } = loadedTranslation;
245
319
  for (const localKey of Object.keys(localTranslations)) {
246
- const phraseKey = getUniqueKey(localKey, loadedTranslation.namespace);
247
- phraseTranslations[language][phraseKey] = localTranslations[localKey];
320
+ var _globalKey;
321
+ const {
322
+ tags = [],
323
+ ...localTranslation
324
+ } = localTranslations[localKey];
325
+ if (language === config.devLanguage) {
326
+ localTranslation.tags = [...tags, ...sharedTags];
327
+ }
328
+ let globalKey;
329
+ if (loadedTranslation.languages[config.devLanguage][localKey].globalKey) {
330
+ globalKey = loadedTranslation.languages[config.devLanguage][localKey].globalKey;
331
+ }
332
+ const phraseKey = (_globalKey = globalKey) !== null && _globalKey !== void 0 ? _globalKey : getUniqueKey(localKey, loadedTranslation.namespace);
333
+ phraseTranslations[language][phraseKey] = localTranslation;
248
334
  }
249
335
  }
250
336
  }
251
-
252
- for (const language of allLanguages) {
253
- if (phraseTranslations[language]) {
254
- const {
255
- uploadId
256
- } = await pushTranslationsByLocale(phraseTranslations[language], language, branch);
257
-
258
- if (deleteUnusedKeys$1) {
259
- await deleteUnusedKeys(uploadId, language, branch);
260
- }
261
- }
337
+ const {
338
+ devLanguageUploadId
339
+ } = await pushTranslations(phraseTranslations, {
340
+ devLanguage: config.devLanguage,
341
+ branch
342
+ });
343
+ if (deleteUnusedKeys$1) {
344
+ await deleteUnusedKeys(devLanguageUploadId, branch);
262
345
  }
263
346
  }
264
347
 
package/package.json CHANGED
@@ -1,19 +1,23 @@
1
1
  {
2
2
  "name": "@vocab/phrase",
3
- "version": "0.0.0-delete-unused-keys-20228144520",
3
+ "version": "0.0.0-global-key-support-20231025223328",
4
4
  "main": "dist/vocab-phrase.cjs.js",
5
5
  "module": "dist/vocab-phrase.esm.js",
6
6
  "author": "SEEK",
7
7
  "license": "MIT",
8
8
  "dependencies": {
9
- "@vocab/core": "^1.0.0",
10
- "@vocab/types": "^1.0.0",
9
+ "@vocab/core": "0.0.0-global-key-support-20231025223328",
11
10
  "chalk": "^4.1.0",
11
+ "csv-stringify": "^6.2.3",
12
12
  "debug": "^4.3.1",
13
13
  "form-data": "^3.0.0",
14
14
  "node-fetch": "^2.6.1"
15
15
  },
16
16
  "devDependencies": {
17
+ "@types/debug": "^4.1.5",
17
18
  "@types/node-fetch": "^2.5.7"
18
- }
19
- }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ]
23
+ }
package/CHANGELOG.md DELETED
@@ -1,128 +0,0 @@
1
- # @vocab/phrase
2
-
3
- ## 0.0.0-delete-unused-keys-20228144520
4
-
5
- ### Minor Changes
6
-
7
- - [`fcd1482`](https://github.com/seek-oss/vocab/commit/fcd1482753e74274935f00ac0fc3afe1bf7f1989) Thanks [@askoufis](https://github.com/askoufis)! - Add an optional `deleteUnusedKeys` flag to the `push` function. If set to `true`, unused keys will be deleted from Phrase after translations are pushed.
8
-
9
- ## 1.0.1
10
-
11
- ### Patch Changes
12
-
13
- - [`20eec77`](https://github.com/seek-oss/vocab/commit/20eec770705d05048ad8b32575cb92720b887f5b) [#76](https://github.com/seek-oss/vocab/pull/76) Thanks [@askoufis](https://github.com/askoufis)! - `vocab pull` no longer errors when phrase returns no translations for a configured language
14
-
15
- ## 1.0.0
16
-
17
- ### Major Changes
18
-
19
- - [`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
20
-
21
- Release Vocab as v1.0.0 to signify a stable API and support future [semver versioning](https://semver.org/) releases.
22
-
23
- 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.
24
-
25
- ### Patch Changes
26
-
27
- - Updated dependencies [[`0074382`](https://github.com/seek-oss/vocab/commit/007438273ef70f5d5ded45777933651ad8df36f6), [`3031054`](https://github.com/seek-oss/vocab/commit/303105440851db6126f0606e1607745b27dd981c)]:
28
- - @vocab/core@1.0.0
29
- - @vocab/types@1.0.0
30
-
31
- ## 0.0.11
32
-
33
- ### Patch Changes
34
-
35
- - Updated dependencies [[`5b1fdc0`](https://github.com/seek-oss/vocab/commit/5b1fdc019522b12e7ef94b2fec57b54a9310d41c)]:
36
- - @vocab/core@0.0.11
37
- - @vocab/types@0.0.9
38
-
39
- ## 0.0.10
40
-
41
- ### Patch Changes
42
-
43
- - Updated dependencies [[`7c96a14`](https://github.com/seek-oss/vocab/commit/7c96a142f602132d38c1df1a47a1f4657dc5c94c)]:
44
- - @vocab/core@0.0.10
45
-
46
- ## 0.0.9
47
-
48
- ### Patch Changes
49
-
50
- - Updated dependencies [[`3034bd3`](https://github.com/seek-oss/vocab/commit/3034bd3de610a9d1f3bfbd8caefa27064dee2710), [`c110745`](https://github.com/seek-oss/vocab/commit/c110745b79df1a8ade6b1d8a49e798b04a7b95e1)]:
51
- - @vocab/core@0.0.9
52
-
53
- ## 0.0.8
54
-
55
- ### Patch Changes
56
-
57
- - Updated dependencies [[`f2fca67`](https://github.com/seek-oss/vocab/commit/f2fca679c66ae65405a0aa24f0a0e472026aad0d)]:
58
- - @vocab/core@0.0.8
59
- - @vocab/types@0.0.8
60
-
61
- ## 0.0.7
62
-
63
- ### Patch Changes
64
-
65
- - [`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
66
-
67
- - Updated dependencies [[`283bcad`](https://github.com/seek-oss/vocab/commit/283bcada06e622ab14ed891743ed3f55cf09e245), [`ad0d240`](https://github.com/seek-oss/vocab/commit/ad0d2404545ded8e11621eae8f29467ff3352366), [`f3992ef`](https://github.com/seek-oss/vocab/commit/f3992efbf08939ebf853fac650a49cc46dc51dfb), [`f3992ef`](https://github.com/seek-oss/vocab/commit/f3992efbf08939ebf853fac650a49cc46dc51dfb)]:
68
- - @vocab/core@0.0.7
69
- - @vocab/types@0.0.7
70
-
71
- ## 0.0.6
72
-
73
- ### Patch Changes
74
-
75
- - [`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
76
-
77
- * [`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
78
-
79
- * Updated dependencies [[`80a46c0`](https://github.com/seek-oss/vocab/commit/80a46c01a55408675f5822c3618519f80136c3ab), [`80a46c0`](https://github.com/seek-oss/vocab/commit/80a46c01a55408675f5822c3618519f80136c3ab)]:
80
- - @vocab/core@0.0.6
81
- - @vocab/types@0.0.6
82
-
83
- ## 0.0.5
84
-
85
- ### Patch Changes
86
-
87
- - Updated dependencies [[`371ed16`](https://github.com/seek-oss/vocab/commit/371ed16a232a04dab13afa7e2b352dfb6724eea4), [`c222d68`](https://github.com/seek-oss/vocab/commit/c222d68a3c0c24723a338eccb959798881f6a118)]:
88
- - @vocab/core@0.0.5
89
-
90
- ## 0.0.4
91
-
92
- ### Patch Changes
93
-
94
- - [`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`.
95
-
96
- The new `vocab compile` step replaces `vocab generate-types` in creating a fully functional **translations.ts** file.
97
-
98
- 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.
99
-
100
- 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.
101
-
102
- See the [documentation](https://github.com/seek-oss/vocab) for further usage details.
103
-
104
- * [`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
105
-
106
- * Updated dependencies [[`5f5c581`](https://github.com/seek-oss/vocab/commit/5f5c581a65bff28729ee19e1ec0bdea488a9d6c2), [`02f943c`](https://github.com/seek-oss/vocab/commit/02f943ca892913b41f9e4720a72400777cf14b3d)]:
107
- - @vocab/core@0.0.4
108
- - @vocab/types@0.0.5
109
-
110
- ## 0.0.3
111
-
112
- ### Patch Changes
113
-
114
- - [`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
115
-
116
- * [`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
117
-
118
- * Updated dependencies [[`08de30d`](https://github.com/seek-oss/vocab/commit/08de30d338c2a5ebdcf14da7c736dddf22e7ca9e), [`ed6cf40`](https://github.com/seek-oss/vocab/commit/ed6cf408973f2e9c4d07a71fcb52f40294ebaf65), [`26b52f4`](https://github.com/seek-oss/vocab/commit/26b52f4878ded440841e08c858bdc9e685500c2a), [`b5a5a05`](https://github.com/seek-oss/vocab/commit/b5a5a05a5bb87b48e6e9160af75f555728143ea2)]:
119
- - @vocab/core@0.0.3
120
- - @vocab/types@0.0.4
121
-
122
- ## 0.0.2
123
-
124
- ### Patch Changes
125
-
126
- - Updated dependencies [[`4710f34`](https://github.com/seek-oss/vocab/commit/4710f341f2827643e3eff69ef7e26d44ec6e8a2b), [`4710f34`](https://github.com/seek-oss/vocab/commit/4710f341f2827643e3eff69ef7e26d44ec6e8a2b)]:
127
- - @vocab/types@0.0.3
128
- - @vocab/core@0.0.2
package/src/file.ts DELETED
@@ -1,4 +0,0 @@
1
- import { promises as fs } from 'fs';
2
-
3
- export const mkdir = fs.mkdir;
4
- export const writeFile = fs.writeFile;
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export { pull } from './pull-translations';
2
- export { push } from './push-translations';
package/src/logger.ts DELETED
@@ -1,9 +0,0 @@
1
- import chalk from 'chalk';
2
- import debug from 'debug';
3
-
4
- export const trace = debug(`vocab:phrase`);
5
-
6
- export const log = (...params: unknown[]) => {
7
- // eslint-disable-next-line no-console
8
- console.log(chalk.yellow('Vocab'), ...params);
9
- };