@vocab/phrase 1.0.0 → 1.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @vocab/phrase
2
2
 
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`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
8
+
3
9
  ## 1.0.0
4
10
 
5
11
  ### Major Changes
package/README.md CHANGED
@@ -110,7 +110,7 @@ So far, your app will run, but you're missing any translations other than the in
110
110
  }
111
111
  ```
112
112
 
113
- ### Step 6: [Optional] Setup Webpack plugin
113
+ ### Step 6: [Optional] Set up Webpack plugin
114
114
 
115
115
  Right now every language is loaded into your web application all the time, which could lead to a large bundle size. Ideally you will want to switch out the Node/default runtime for web runtime that will load only the active language.
116
116
 
@@ -171,8 +171,10 @@ In the below example we use two messages, one that passes in a single parameter
171
171
  Vocab will automatically parse these strings as ICU messages, identify the required parameters and ensure TypeScript knows the values must be passed in.
172
172
 
173
173
  ```tsx
174
- t('my key with param', {name: 'Vocab'});
175
- t('my key with component', {Link: children => (<a href="/foo">{children}</Link>)});
174
+ t('my key with param', { name: 'Vocab' });
175
+ t('my key with component', {
176
+ Link: (children) => <a href="/foo">{children}</a>
177
+ });
176
178
  ```
177
179
 
178
180
  ## Configuration
@@ -194,7 +196,7 @@ module.exports = {
194
196
  * The root directory to compile and validate translations
195
197
  * Default: Current working directory
196
198
  */
197
- projectRoot: ['./example/'];
199
+ projectRoot: './example/';
198
200
  /**
199
201
  * A custom suffix to name vocab translation directories
200
202
  * Default: '.vocab'
@@ -83,7 +83,6 @@ async function callPhrase(relativePath, options = {}) {
83
83
  }
84
84
 
85
85
  return _callPhrase(`https://api.phrase.com/v2/projects/${projectId}/${relativePath}`, options).then(result => {
86
- // console.log('Result:', result);
87
86
  if (Array.isArray(result)) {
88
87
  console.log('Result length:', result.length);
89
88
  }
@@ -174,31 +173,33 @@ async function pull({
174
173
  await writeFile(loadedTranslation.filePath, `${JSON.stringify(defaultValues, null, 2)}\n`);
175
174
 
176
175
  for (const alternativeLanguage of alternativeLanguages) {
177
- const altTranslations = { ...loadedTranslation.languages[alternativeLanguage]
178
- };
179
- const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
176
+ if (alternativeLanguage in allPhraseTranslations) {
177
+ const altTranslations = { ...loadedTranslation.languages[alternativeLanguage]
178
+ };
179
+ const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
180
+
181
+ for (const key of localKeys) {
182
+ var _phraseAltTranslation;
180
183
 
181
- for (const key of localKeys) {
182
- var _phraseAltTranslation;
184
+ const phraseKey = core.getUniqueKey(key, loadedTranslation.namespace);
185
+ const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
183
186
 
184
- const phraseKey = core.getUniqueKey(key, loadedTranslation.namespace);
185
- const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
187
+ if (!phraseTranslationMessage) {
188
+ trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
189
+ continue;
190
+ }
186
191
 
187
- if (!phraseTranslationMessage) {
188
- trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
189
- continue;
192
+ altTranslations[key] = { ...altTranslations[key],
193
+ message: phraseTranslationMessage
194
+ };
190
195
  }
191
196
 
192
- altTranslations[key] = { ...altTranslations[key],
193
- message: phraseTranslationMessage
194
- };
197
+ const altTranslationFilePath = core.getAltLanguageFilePath(loadedTranslation.filePath, alternativeLanguage);
198
+ await mkdir(path__default['default'].dirname(altTranslationFilePath), {
199
+ recursive: true
200
+ });
201
+ await writeFile(altTranslationFilePath, `${JSON.stringify(altTranslations, null, 2)}\n`);
195
202
  }
196
-
197
- const altTranslationFilePath = core.getAltLanguageFilePath(loadedTranslation.filePath, alternativeLanguage);
198
- await mkdir(path__default['default'].dirname(altTranslationFilePath), {
199
- recursive: true
200
- });
201
- await writeFile(altTranslationFilePath, `${JSON.stringify(altTranslations, null, 2)}\n`);
202
203
  }
203
204
  }
204
205
  }
@@ -83,7 +83,6 @@ async function callPhrase(relativePath, options = {}) {
83
83
  }
84
84
 
85
85
  return _callPhrase(`https://api.phrase.com/v2/projects/${projectId}/${relativePath}`, options).then(result => {
86
- // console.log('Result:', result);
87
86
  if (Array.isArray(result)) {
88
87
  console.log('Result length:', result.length);
89
88
  }
@@ -174,31 +173,33 @@ async function pull({
174
173
  await writeFile(loadedTranslation.filePath, `${JSON.stringify(defaultValues, null, 2)}\n`);
175
174
 
176
175
  for (const alternativeLanguage of alternativeLanguages) {
177
- const altTranslations = { ...loadedTranslation.languages[alternativeLanguage]
178
- };
179
- const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
176
+ if (alternativeLanguage in allPhraseTranslations) {
177
+ const altTranslations = { ...loadedTranslation.languages[alternativeLanguage]
178
+ };
179
+ const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
180
+
181
+ for (const key of localKeys) {
182
+ var _phraseAltTranslation;
180
183
 
181
- for (const key of localKeys) {
182
- var _phraseAltTranslation;
184
+ const phraseKey = core.getUniqueKey(key, loadedTranslation.namespace);
185
+ const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
183
186
 
184
- const phraseKey = core.getUniqueKey(key, loadedTranslation.namespace);
185
- const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
187
+ if (!phraseTranslationMessage) {
188
+ trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
189
+ continue;
190
+ }
186
191
 
187
- if (!phraseTranslationMessage) {
188
- trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
189
- continue;
192
+ altTranslations[key] = { ...altTranslations[key],
193
+ message: phraseTranslationMessage
194
+ };
190
195
  }
191
196
 
192
- altTranslations[key] = { ...altTranslations[key],
193
- message: phraseTranslationMessage
194
- };
197
+ const altTranslationFilePath = core.getAltLanguageFilePath(loadedTranslation.filePath, alternativeLanguage);
198
+ await mkdir(path__default['default'].dirname(altTranslationFilePath), {
199
+ recursive: true
200
+ });
201
+ await writeFile(altTranslationFilePath, `${JSON.stringify(altTranslations, null, 2)}\n`);
195
202
  }
196
-
197
- const altTranslationFilePath = core.getAltLanguageFilePath(loadedTranslation.filePath, alternativeLanguage);
198
- await mkdir(path__default['default'].dirname(altTranslationFilePath), {
199
- recursive: true
200
- });
201
- await writeFile(altTranslationFilePath, `${JSON.stringify(altTranslations, null, 2)}\n`);
202
203
  }
203
204
  }
204
205
  }
@@ -71,7 +71,6 @@ async function callPhrase(relativePath, options = {}) {
71
71
  }
72
72
 
73
73
  return _callPhrase(`https://api.phrase.com/v2/projects/${projectId}/${relativePath}`, options).then(result => {
74
- // console.log('Result:', result);
75
74
  if (Array.isArray(result)) {
76
75
  console.log('Result length:', result.length);
77
76
  }
@@ -162,31 +161,33 @@ async function pull({
162
161
  await writeFile(loadedTranslation.filePath, `${JSON.stringify(defaultValues, null, 2)}\n`);
163
162
 
164
163
  for (const alternativeLanguage of alternativeLanguages) {
165
- const altTranslations = { ...loadedTranslation.languages[alternativeLanguage]
166
- };
167
- const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
164
+ if (alternativeLanguage in allPhraseTranslations) {
165
+ const altTranslations = { ...loadedTranslation.languages[alternativeLanguage]
166
+ };
167
+ const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
168
+
169
+ for (const key of localKeys) {
170
+ var _phraseAltTranslation;
168
171
 
169
- for (const key of localKeys) {
170
- var _phraseAltTranslation;
172
+ const phraseKey = getUniqueKey(key, loadedTranslation.namespace);
173
+ const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
171
174
 
172
- const phraseKey = getUniqueKey(key, loadedTranslation.namespace);
173
- const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
175
+ if (!phraseTranslationMessage) {
176
+ trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
177
+ continue;
178
+ }
174
179
 
175
- if (!phraseTranslationMessage) {
176
- trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
177
- continue;
180
+ altTranslations[key] = { ...altTranslations[key],
181
+ message: phraseTranslationMessage
182
+ };
178
183
  }
179
184
 
180
- altTranslations[key] = { ...altTranslations[key],
181
- message: phraseTranslationMessage
182
- };
185
+ const altTranslationFilePath = getAltLanguageFilePath(loadedTranslation.filePath, alternativeLanguage);
186
+ await mkdir(path.dirname(altTranslationFilePath), {
187
+ recursive: true
188
+ });
189
+ await writeFile(altTranslationFilePath, `${JSON.stringify(altTranslations, null, 2)}\n`);
183
190
  }
184
-
185
- const altTranslationFilePath = getAltLanguageFilePath(loadedTranslation.filePath, alternativeLanguage);
186
- await mkdir(path.dirname(altTranslationFilePath), {
187
- recursive: true
188
- });
189
- await writeFile(altTranslationFilePath, `${JSON.stringify(altTranslations, null, 2)}\n`);
190
191
  }
191
192
  }
192
193
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vocab/phrase",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "main": "dist/vocab-phrase.cjs.js",
5
5
  "module": "dist/vocab-phrase.esm.js",
6
6
  "author": "SEEK",
package/src/phrase-api.ts CHANGED
@@ -80,7 +80,6 @@ export async function callPhrase(
80
80
  options,
81
81
  )
82
82
  .then((result) => {
83
- // console.log('Result:', result);
84
83
  if (Array.isArray(result)) {
85
84
  console.log('Result length:', result.length);
86
85
  }
@@ -2,6 +2,7 @@ import path from 'path';
2
2
  import { pull } from './pull-translations';
3
3
  import { pullAllTranslations } from './phrase-api';
4
4
  import { writeFile } from './file';
5
+ import { LanguageTarget } from '@vocab/types';
5
6
 
6
7
  jest.mock('./file', () => ({
7
8
  writeFile: jest.fn(() => Promise.resolve),
@@ -13,28 +14,83 @@ jest.mock('./phrase-api', () => ({
13
14
  pullAllTranslations: jest.fn(() => Promise.resolve({ en: {}, fr: {} })),
14
15
  }));
15
16
 
16
- function runPhrase() {
17
+ function runPhrase(options: { languages: LanguageTarget[] }) {
17
18
  return pull(
18
19
  { branch: 'tester' },
19
20
  {
21
+ ...options,
20
22
  devLanguage: 'en',
21
- languages: [{ name: 'en' }, { name: 'fr' }],
22
23
  projectRoot: path.resolve(__dirname, '..', '..', '..', 'fixtures/phrase'),
23
24
  },
24
25
  );
25
26
  }
26
27
 
27
- describe('pull', () => {
28
- beforeEach(() => {
29
- (pullAllTranslations as jest.Mock).mockClear();
30
- (writeFile as jest.Mock).mockClear();
31
- });
32
- it('should resolve', async () => {
33
- await expect(runPhrase()).resolves.toBeUndefined();
28
+ describe('pull translations', () => {
29
+ describe('when pulling translations for languages that already have translations', () => {
30
+ beforeEach(() => {
31
+ (pullAllTranslations as jest.Mock).mockClear();
32
+ (writeFile as jest.Mock).mockClear();
33
+ });
34
+ (pullAllTranslations as jest.Mock).mockImplementation(() =>
35
+ Promise.resolve({
36
+ en: {
37
+ 'hello.mytranslations': {
38
+ message: 'Hi there',
39
+ },
40
+ },
41
+ fr: {
42
+ 'hello.mytranslations': {
43
+ message: 'merci',
44
+ },
45
+ },
46
+ }),
47
+ );
34
48
 
35
- expect(writeFile as jest.Mock).toHaveBeenCalledTimes(2);
49
+ const options = {
50
+ languages: [{ name: 'en' }, { name: 'fr' }],
51
+ };
52
+
53
+ it('should resolve', async () => {
54
+ await expect(runPhrase(options)).resolves.toBeUndefined();
55
+
56
+ expect(writeFile as jest.Mock).toHaveBeenCalledTimes(2);
57
+ });
58
+
59
+ it('should update keys', async () => {
60
+ await expect(runPhrase(options)).resolves.toBeUndefined();
61
+
62
+ expect(
63
+ (writeFile as jest.Mock).mock.calls.map(
64
+ ([_filePath, contents]: [string, string]) => JSON.parse(contents),
65
+ ),
66
+ ).toMatchInlineSnapshot(`
67
+ Array [
68
+ Object {
69
+ "hello": Object {
70
+ "message": "Hi there",
71
+ },
72
+ "world": Object {
73
+ "message": "world",
74
+ },
75
+ },
76
+ Object {
77
+ "hello": Object {
78
+ "message": "merci",
79
+ },
80
+ "world": Object {
81
+ "message": "monde",
82
+ },
83
+ },
84
+ ]
85
+ `);
86
+ });
36
87
  });
37
- it('should update keys', async () => {
88
+
89
+ describe('when pulling translations and some languages do not have any translations', () => {
90
+ beforeEach(() => {
91
+ (pullAllTranslations as jest.Mock).mockClear();
92
+ (writeFile as jest.Mock).mockClear();
93
+ });
38
94
  (pullAllTranslations as jest.Mock).mockImplementation(() =>
39
95
  Promise.resolve({
40
96
  en: {
@@ -50,13 +106,24 @@ describe('pull', () => {
50
106
  }),
51
107
  );
52
108
 
53
- await expect(runPhrase()).resolves.toBeUndefined();
109
+ const options = {
110
+ languages: [{ name: 'en' }, { name: 'fr' }, { name: 'ja' }],
111
+ };
112
+
113
+ it('should resolve', async () => {
114
+ await expect(runPhrase(options)).resolves.toBeUndefined();
115
+
116
+ expect(writeFile as jest.Mock).toHaveBeenCalledTimes(2);
117
+ });
118
+
119
+ it('should update keys', async () => {
120
+ await expect(runPhrase(options)).resolves.toBeUndefined();
54
121
 
55
- expect(
56
- (writeFile as jest.Mock).mock.calls.map(
57
- ([_filePath, contents]: [string, string]) => JSON.parse(contents),
58
- ),
59
- ).toMatchInlineSnapshot(`
122
+ expect(
123
+ (writeFile as jest.Mock).mock.calls.map(
124
+ ([_filePath, contents]: [string, string]) => JSON.parse(contents),
125
+ ),
126
+ ).toMatchInlineSnapshot(`
60
127
  Array [
61
128
  Object {
62
129
  "hello": Object {
@@ -76,5 +143,6 @@ describe('pull', () => {
76
143
  },
77
144
  ]
78
145
  `);
146
+ });
79
147
  });
80
148
  });
@@ -59,41 +59,44 @@ export async function pull(
59
59
  );
60
60
 
61
61
  for (const alternativeLanguage of alternativeLanguages) {
62
- const altTranslations = {
63
- ...loadedTranslation.languages[alternativeLanguage],
64
- };
65
- const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
62
+ if (alternativeLanguage in allPhraseTranslations) {
63
+ const altTranslations = {
64
+ ...loadedTranslation.languages[alternativeLanguage],
65
+ };
66
+ const phraseAltTranslations =
67
+ allPhraseTranslations[alternativeLanguage];
66
68
 
67
- for (const key of localKeys) {
68
- const phraseKey = getUniqueKey(key, loadedTranslation.namespace);
69
- const phraseTranslationMessage =
70
- phraseAltTranslations[phraseKey]?.message;
69
+ for (const key of localKeys) {
70
+ const phraseKey = getUniqueKey(key, loadedTranslation.namespace);
71
+ const phraseTranslationMessage =
72
+ phraseAltTranslations[phraseKey]?.message;
71
73
 
72
- if (!phraseTranslationMessage) {
73
- trace(
74
- `Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`,
75
- );
76
- continue;
77
- }
74
+ if (!phraseTranslationMessage) {
75
+ trace(
76
+ `Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`,
77
+ );
78
+ continue;
79
+ }
78
80
 
79
- altTranslations[key] = {
80
- ...altTranslations[key],
81
- message: phraseTranslationMessage,
82
- };
83
- }
81
+ altTranslations[key] = {
82
+ ...altTranslations[key],
83
+ message: phraseTranslationMessage,
84
+ };
85
+ }
84
86
 
85
- const altTranslationFilePath = getAltLanguageFilePath(
86
- loadedTranslation.filePath,
87
- alternativeLanguage,
88
- );
87
+ const altTranslationFilePath = getAltLanguageFilePath(
88
+ loadedTranslation.filePath,
89
+ alternativeLanguage,
90
+ );
89
91
 
90
- await mkdir(path.dirname(altTranslationFilePath), {
91
- recursive: true,
92
- });
93
- await writeFile(
94
- altTranslationFilePath,
95
- `${JSON.stringify(altTranslations, null, 2)}\n`,
96
- );
92
+ await mkdir(path.dirname(altTranslationFilePath), {
93
+ recursive: true,
94
+ });
95
+ await writeFile(
96
+ altTranslationFilePath,
97
+ `${JSON.stringify(altTranslations, null, 2)}\n`,
98
+ );
99
+ }
97
100
  }
98
101
  }
99
102
  }