@vocab/phrase 0.0.0-compiled-translation-import-order-20230328231631 → 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.
- package/dist/declarations/src/csv.d.ts +4 -4
- package/dist/declarations/src/phrase-api.d.ts +2 -2
- package/dist/declarations/src/pull-translations.d.ts +3 -2
- package/dist/declarations/src/push-translations.d.ts +1 -1
- package/dist/vocab-phrase.cjs.dev.js +78 -54
- package/dist/vocab-phrase.cjs.prod.js +78 -54
- package/dist/vocab-phrase.esm.js +78 -54
- package/package.json +2 -3
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { TranslationsByLanguage } from '@vocab/
|
|
1
|
+
import type { TranslationsByLanguage } from '@vocab/core';
|
|
2
2
|
export declare function translationsToCsv(translations: TranslationsByLanguage, devLanguage: string): {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
[k: string]: number;
|
|
3
|
+
csvFileStrings: {
|
|
4
|
+
[k: string]: string;
|
|
6
5
|
};
|
|
7
6
|
keyIndex: number;
|
|
7
|
+
messageIndex: number;
|
|
8
8
|
commentIndex: number;
|
|
9
9
|
tagColumn: number;
|
|
10
10
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TranslationsByLanguage } from '@vocab/
|
|
1
|
+
import type { TranslationsByLanguage } from '@vocab/core';
|
|
2
2
|
import fetch from 'node-fetch';
|
|
3
3
|
export declare function callPhrase<T = any>(relativePath: string, options?: Parameters<typeof fetch>[1]): Promise<T>;
|
|
4
4
|
export declare function pullAllTranslations(branch: string): Promise<TranslationsByLanguage>;
|
|
@@ -6,7 +6,7 @@ export declare function pushTranslations(translationsByLanguage: TranslationsByL
|
|
|
6
6
|
devLanguage: string;
|
|
7
7
|
branch: string;
|
|
8
8
|
}): Promise<{
|
|
9
|
-
|
|
9
|
+
devLanguageUploadId: string;
|
|
10
10
|
}>;
|
|
11
11
|
export declare function deleteUnusedKeys(uploadId: string, branch: string): Promise<void>;
|
|
12
12
|
export declare function ensureBranch(branch: string): Promise<void>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { UserConfig } from '@vocab/
|
|
1
|
+
import type { UserConfig } from '@vocab/core';
|
|
2
2
|
interface PullOptions {
|
|
3
3
|
branch?: string;
|
|
4
4
|
deleteUnusedKeys?: boolean;
|
|
5
|
+
errorOnNoGlobalKeyTranslation?: boolean;
|
|
5
6
|
}
|
|
6
|
-
export declare function pull({ branch }: PullOptions, config: UserConfig): Promise<void>;
|
|
7
|
+
export declare function pull({ branch, errorOnNoGlobalKeyTranslation }: PullOptions, config: UserConfig): Promise<void>;
|
|
7
8
|
export {};
|
|
@@ -31,34 +31,43 @@ const log = (...params) => {
|
|
|
31
31
|
function translationsToCsv(translations, devLanguage) {
|
|
32
32
|
const languages = Object.keys(translations);
|
|
33
33
|
const altLanguages = languages.filter(language => language !== devLanguage);
|
|
34
|
-
// Ensure languages are ordered for locale mapping
|
|
35
|
-
const orderedLanguages = [devLanguage, ...altLanguages];
|
|
36
34
|
const devLanguageTranslations = translations[devLanguage];
|
|
37
|
-
const
|
|
35
|
+
const csvFilesByLanguage = Object.fromEntries(languages.map(language => [language, []]));
|
|
36
|
+
Object.entries(devLanguageTranslations).map(([key, {
|
|
38
37
|
message,
|
|
39
38
|
description,
|
|
40
39
|
tags
|
|
41
40
|
}]) => {
|
|
42
|
-
const
|
|
41
|
+
const sharedData = [key, description, tags === null || tags === void 0 ? void 0 : tags.join(',')];
|
|
42
|
+
const devLanguageRow = [...sharedData, message];
|
|
43
|
+
csvFilesByLanguage[devLanguage].push(devLanguageRow);
|
|
44
|
+
altLanguages.map(language => {
|
|
43
45
|
var _translations$languag, _translations$languag2;
|
|
44
|
-
|
|
46
|
+
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;
|
|
47
|
+
if (altTranslationMessage) {
|
|
48
|
+
csvFilesByLanguage[language].push([...sharedData, altTranslationMessage]);
|
|
49
|
+
}
|
|
45
50
|
});
|
|
46
|
-
return [message, ...altTranslationMessages, key, description, tags === null || tags === void 0 ? void 0 : tags.join(',')];
|
|
47
|
-
});
|
|
48
|
-
const csvString = sync.stringify(csv, {
|
|
49
|
-
delimiter: ',',
|
|
50
|
-
header: false
|
|
51
51
|
});
|
|
52
|
+
const csvFileStrings = Object.fromEntries(Object.entries(csvFilesByLanguage)
|
|
53
|
+
// Ensure CSV files are only created if the language has at least 1 translation
|
|
54
|
+
.filter(([_, csvFile]) => csvFile.length > 0).map(([language, csvFile]) => {
|
|
55
|
+
const csvFileString = sync.stringify(csvFile, {
|
|
56
|
+
delimiter: ',',
|
|
57
|
+
header: false
|
|
58
|
+
});
|
|
59
|
+
return [language, csvFileString];
|
|
60
|
+
}));
|
|
52
61
|
|
|
53
62
|
// Column indices start at 1
|
|
54
|
-
const
|
|
55
|
-
const keyIndex = orderedLanguages.length + 1;
|
|
63
|
+
const keyIndex = 1;
|
|
56
64
|
const commentIndex = keyIndex + 1;
|
|
57
65
|
const tagColumn = commentIndex + 1;
|
|
66
|
+
const messageIndex = tagColumn + 1;
|
|
58
67
|
return {
|
|
59
|
-
|
|
60
|
-
localeMapping,
|
|
68
|
+
csvFileStrings,
|
|
61
69
|
keyIndex,
|
|
70
|
+
messageIndex,
|
|
62
71
|
commentIndex,
|
|
63
72
|
tagColumn
|
|
64
73
|
};
|
|
@@ -139,45 +148,50 @@ async function pushTranslations(translationsByLanguage, {
|
|
|
139
148
|
devLanguage,
|
|
140
149
|
branch
|
|
141
150
|
}) {
|
|
142
|
-
const formData = new FormData__default["default"]();
|
|
143
151
|
const {
|
|
144
|
-
|
|
145
|
-
localeMapping,
|
|
152
|
+
csvFileStrings,
|
|
146
153
|
keyIndex,
|
|
147
154
|
commentIndex,
|
|
148
|
-
tagColumn
|
|
155
|
+
tagColumn,
|
|
156
|
+
messageIndex
|
|
149
157
|
} = translationsToCsv(translationsByLanguage, devLanguage);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
formData.append(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
158
|
+
let devLanguageUploadId = '';
|
|
159
|
+
for (const [language, csvFileString] of Object.entries(csvFileStrings)) {
|
|
160
|
+
const formData = new FormData__default["default"]();
|
|
161
|
+
const fileContents = Buffer.from(csvFileString);
|
|
162
|
+
formData.append('file', fileContents, {
|
|
163
|
+
contentType: 'text/csv',
|
|
164
|
+
filename: `${language}.translations.csv`
|
|
165
|
+
});
|
|
166
|
+
formData.append('file_format', 'csv');
|
|
167
|
+
formData.append('branch', branch);
|
|
168
|
+
formData.append('update_translations', 'true');
|
|
169
|
+
formData.append('update_descriptions', 'true');
|
|
170
|
+
formData.append(`locale_mapping[${language}]`, messageIndex);
|
|
171
|
+
formData.append('format_options[key_index]', keyIndex);
|
|
172
|
+
formData.append('format_options[comment_index]', commentIndex);
|
|
173
|
+
formData.append('format_options[tag_column]', tagColumn);
|
|
174
|
+
formData.append('format_options[enable_pluralization]', 'false');
|
|
175
|
+
log(`Uploading translations for language ${language}`);
|
|
176
|
+
const result = await callPhrase(`uploads`, {
|
|
177
|
+
method: 'POST',
|
|
178
|
+
body: formData
|
|
179
|
+
});
|
|
180
|
+
trace('Upload result:\n', result);
|
|
181
|
+
if (result && 'id' in result) {
|
|
182
|
+
log('Upload ID:', result.id, '\n');
|
|
183
|
+
log('Successfully Uploaded\n');
|
|
184
|
+
} else {
|
|
185
|
+
log(`Error uploading: ${result === null || result === void 0 ? void 0 : result.message}\n`);
|
|
186
|
+
log('Response:', result);
|
|
187
|
+
throw new Error('Error uploading');
|
|
188
|
+
}
|
|
189
|
+
if (language === devLanguage) {
|
|
190
|
+
devLanguageUploadId = result.id;
|
|
191
|
+
}
|
|
178
192
|
}
|
|
179
193
|
return {
|
|
180
|
-
|
|
194
|
+
devLanguageUploadId
|
|
181
195
|
};
|
|
182
196
|
}
|
|
183
197
|
async function deleteUnusedKeys(uploadId, branch) {
|
|
@@ -210,7 +224,8 @@ async function ensureBranch(branch) {
|
|
|
210
224
|
}
|
|
211
225
|
|
|
212
226
|
async function pull({
|
|
213
|
-
branch = 'local-development'
|
|
227
|
+
branch = 'local-development',
|
|
228
|
+
errorOnNoGlobalKeyTranslation
|
|
214
229
|
}, config) {
|
|
215
230
|
trace(`Pulling translations from branch ${branch}`);
|
|
216
231
|
await ensureBranch(branch);
|
|
@@ -237,9 +252,10 @@ async function pull({
|
|
|
237
252
|
};
|
|
238
253
|
const localKeys = Object.keys(defaultValues);
|
|
239
254
|
for (const key of localKeys) {
|
|
255
|
+
var _defaultValues$key$gl;
|
|
240
256
|
defaultValues[key] = {
|
|
241
257
|
...defaultValues[key],
|
|
242
|
-
...allPhraseTranslations[config.devLanguage][core.getUniqueKey(key, loadedTranslation.namespace)]
|
|
258
|
+
...allPhraseTranslations[config.devLanguage][(_defaultValues$key$gl = defaultValues[key].globalKey) !== null && _defaultValues$key$gl !== void 0 ? _defaultValues$key$gl : core.getUniqueKey(key, loadedTranslation.namespace)]
|
|
243
259
|
};
|
|
244
260
|
}
|
|
245
261
|
|
|
@@ -255,11 +271,14 @@ async function pull({
|
|
|
255
271
|
};
|
|
256
272
|
const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
|
|
257
273
|
for (const key of localKeys) {
|
|
258
|
-
var _phraseAltTranslation;
|
|
259
|
-
const phraseKey = core.getUniqueKey(key, loadedTranslation.namespace);
|
|
274
|
+
var _defaultValues$key$gl2, _phraseAltTranslation;
|
|
275
|
+
const phraseKey = (_defaultValues$key$gl2 = defaultValues[key].globalKey) !== null && _defaultValues$key$gl2 !== void 0 ? _defaultValues$key$gl2 : core.getUniqueKey(key, loadedTranslation.namespace);
|
|
260
276
|
const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
|
|
261
277
|
if (!phraseTranslationMessage) {
|
|
262
278
|
trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
|
|
279
|
+
if (errorOnNoGlobalKeyTranslation && defaultValues[key].globalKey) {
|
|
280
|
+
throw new Error(`Missing translation for global key ${key} in language ${alternativeLanguage}`);
|
|
281
|
+
}
|
|
263
282
|
continue;
|
|
264
283
|
}
|
|
265
284
|
altTranslations[key] = {
|
|
@@ -310,7 +329,7 @@ async function push({
|
|
|
310
329
|
}
|
|
311
330
|
} = loadedTranslation;
|
|
312
331
|
for (const localKey of Object.keys(localTranslations)) {
|
|
313
|
-
|
|
332
|
+
var _globalKey;
|
|
314
333
|
const {
|
|
315
334
|
tags = [],
|
|
316
335
|
...localTranslation
|
|
@@ -318,18 +337,23 @@ async function push({
|
|
|
318
337
|
if (language === config.devLanguage) {
|
|
319
338
|
localTranslation.tags = [...tags, ...sharedTags];
|
|
320
339
|
}
|
|
340
|
+
let globalKey;
|
|
341
|
+
if (loadedTranslation.languages[config.devLanguage][localKey].globalKey) {
|
|
342
|
+
globalKey = loadedTranslation.languages[config.devLanguage][localKey].globalKey;
|
|
343
|
+
}
|
|
344
|
+
const phraseKey = (_globalKey = globalKey) !== null && _globalKey !== void 0 ? _globalKey : core.getUniqueKey(localKey, loadedTranslation.namespace);
|
|
321
345
|
phraseTranslations[language][phraseKey] = localTranslation;
|
|
322
346
|
}
|
|
323
347
|
}
|
|
324
348
|
}
|
|
325
349
|
const {
|
|
326
|
-
|
|
350
|
+
devLanguageUploadId
|
|
327
351
|
} = await pushTranslations(phraseTranslations, {
|
|
328
352
|
devLanguage: config.devLanguage,
|
|
329
353
|
branch
|
|
330
354
|
});
|
|
331
355
|
if (deleteUnusedKeys$1) {
|
|
332
|
-
await deleteUnusedKeys(
|
|
356
|
+
await deleteUnusedKeys(devLanguageUploadId, branch);
|
|
333
357
|
}
|
|
334
358
|
}
|
|
335
359
|
|
|
@@ -31,34 +31,43 @@ const log = (...params) => {
|
|
|
31
31
|
function translationsToCsv(translations, devLanguage) {
|
|
32
32
|
const languages = Object.keys(translations);
|
|
33
33
|
const altLanguages = languages.filter(language => language !== devLanguage);
|
|
34
|
-
// Ensure languages are ordered for locale mapping
|
|
35
|
-
const orderedLanguages = [devLanguage, ...altLanguages];
|
|
36
34
|
const devLanguageTranslations = translations[devLanguage];
|
|
37
|
-
const
|
|
35
|
+
const csvFilesByLanguage = Object.fromEntries(languages.map(language => [language, []]));
|
|
36
|
+
Object.entries(devLanguageTranslations).map(([key, {
|
|
38
37
|
message,
|
|
39
38
|
description,
|
|
40
39
|
tags
|
|
41
40
|
}]) => {
|
|
42
|
-
const
|
|
41
|
+
const sharedData = [key, description, tags === null || tags === void 0 ? void 0 : tags.join(',')];
|
|
42
|
+
const devLanguageRow = [...sharedData, message];
|
|
43
|
+
csvFilesByLanguage[devLanguage].push(devLanguageRow);
|
|
44
|
+
altLanguages.map(language => {
|
|
43
45
|
var _translations$languag, _translations$languag2;
|
|
44
|
-
|
|
46
|
+
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;
|
|
47
|
+
if (altTranslationMessage) {
|
|
48
|
+
csvFilesByLanguage[language].push([...sharedData, altTranslationMessage]);
|
|
49
|
+
}
|
|
45
50
|
});
|
|
46
|
-
return [message, ...altTranslationMessages, key, description, tags === null || tags === void 0 ? void 0 : tags.join(',')];
|
|
47
|
-
});
|
|
48
|
-
const csvString = sync.stringify(csv, {
|
|
49
|
-
delimiter: ',',
|
|
50
|
-
header: false
|
|
51
51
|
});
|
|
52
|
+
const csvFileStrings = Object.fromEntries(Object.entries(csvFilesByLanguage)
|
|
53
|
+
// Ensure CSV files are only created if the language has at least 1 translation
|
|
54
|
+
.filter(([_, csvFile]) => csvFile.length > 0).map(([language, csvFile]) => {
|
|
55
|
+
const csvFileString = sync.stringify(csvFile, {
|
|
56
|
+
delimiter: ',',
|
|
57
|
+
header: false
|
|
58
|
+
});
|
|
59
|
+
return [language, csvFileString];
|
|
60
|
+
}));
|
|
52
61
|
|
|
53
62
|
// Column indices start at 1
|
|
54
|
-
const
|
|
55
|
-
const keyIndex = orderedLanguages.length + 1;
|
|
63
|
+
const keyIndex = 1;
|
|
56
64
|
const commentIndex = keyIndex + 1;
|
|
57
65
|
const tagColumn = commentIndex + 1;
|
|
66
|
+
const messageIndex = tagColumn + 1;
|
|
58
67
|
return {
|
|
59
|
-
|
|
60
|
-
localeMapping,
|
|
68
|
+
csvFileStrings,
|
|
61
69
|
keyIndex,
|
|
70
|
+
messageIndex,
|
|
62
71
|
commentIndex,
|
|
63
72
|
tagColumn
|
|
64
73
|
};
|
|
@@ -139,45 +148,50 @@ async function pushTranslations(translationsByLanguage, {
|
|
|
139
148
|
devLanguage,
|
|
140
149
|
branch
|
|
141
150
|
}) {
|
|
142
|
-
const formData = new FormData__default["default"]();
|
|
143
151
|
const {
|
|
144
|
-
|
|
145
|
-
localeMapping,
|
|
152
|
+
csvFileStrings,
|
|
146
153
|
keyIndex,
|
|
147
154
|
commentIndex,
|
|
148
|
-
tagColumn
|
|
155
|
+
tagColumn,
|
|
156
|
+
messageIndex
|
|
149
157
|
} = translationsToCsv(translationsByLanguage, devLanguage);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
formData.append(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
158
|
+
let devLanguageUploadId = '';
|
|
159
|
+
for (const [language, csvFileString] of Object.entries(csvFileStrings)) {
|
|
160
|
+
const formData = new FormData__default["default"]();
|
|
161
|
+
const fileContents = Buffer.from(csvFileString);
|
|
162
|
+
formData.append('file', fileContents, {
|
|
163
|
+
contentType: 'text/csv',
|
|
164
|
+
filename: `${language}.translations.csv`
|
|
165
|
+
});
|
|
166
|
+
formData.append('file_format', 'csv');
|
|
167
|
+
formData.append('branch', branch);
|
|
168
|
+
formData.append('update_translations', 'true');
|
|
169
|
+
formData.append('update_descriptions', 'true');
|
|
170
|
+
formData.append(`locale_mapping[${language}]`, messageIndex);
|
|
171
|
+
formData.append('format_options[key_index]', keyIndex);
|
|
172
|
+
formData.append('format_options[comment_index]', commentIndex);
|
|
173
|
+
formData.append('format_options[tag_column]', tagColumn);
|
|
174
|
+
formData.append('format_options[enable_pluralization]', 'false');
|
|
175
|
+
log(`Uploading translations for language ${language}`);
|
|
176
|
+
const result = await callPhrase(`uploads`, {
|
|
177
|
+
method: 'POST',
|
|
178
|
+
body: formData
|
|
179
|
+
});
|
|
180
|
+
trace('Upload result:\n', result);
|
|
181
|
+
if (result && 'id' in result) {
|
|
182
|
+
log('Upload ID:', result.id, '\n');
|
|
183
|
+
log('Successfully Uploaded\n');
|
|
184
|
+
} else {
|
|
185
|
+
log(`Error uploading: ${result === null || result === void 0 ? void 0 : result.message}\n`);
|
|
186
|
+
log('Response:', result);
|
|
187
|
+
throw new Error('Error uploading');
|
|
188
|
+
}
|
|
189
|
+
if (language === devLanguage) {
|
|
190
|
+
devLanguageUploadId = result.id;
|
|
191
|
+
}
|
|
178
192
|
}
|
|
179
193
|
return {
|
|
180
|
-
|
|
194
|
+
devLanguageUploadId
|
|
181
195
|
};
|
|
182
196
|
}
|
|
183
197
|
async function deleteUnusedKeys(uploadId, branch) {
|
|
@@ -210,7 +224,8 @@ async function ensureBranch(branch) {
|
|
|
210
224
|
}
|
|
211
225
|
|
|
212
226
|
async function pull({
|
|
213
|
-
branch = 'local-development'
|
|
227
|
+
branch = 'local-development',
|
|
228
|
+
errorOnNoGlobalKeyTranslation
|
|
214
229
|
}, config) {
|
|
215
230
|
trace(`Pulling translations from branch ${branch}`);
|
|
216
231
|
await ensureBranch(branch);
|
|
@@ -237,9 +252,10 @@ async function pull({
|
|
|
237
252
|
};
|
|
238
253
|
const localKeys = Object.keys(defaultValues);
|
|
239
254
|
for (const key of localKeys) {
|
|
255
|
+
var _defaultValues$key$gl;
|
|
240
256
|
defaultValues[key] = {
|
|
241
257
|
...defaultValues[key],
|
|
242
|
-
...allPhraseTranslations[config.devLanguage][core.getUniqueKey(key, loadedTranslation.namespace)]
|
|
258
|
+
...allPhraseTranslations[config.devLanguage][(_defaultValues$key$gl = defaultValues[key].globalKey) !== null && _defaultValues$key$gl !== void 0 ? _defaultValues$key$gl : core.getUniqueKey(key, loadedTranslation.namespace)]
|
|
243
259
|
};
|
|
244
260
|
}
|
|
245
261
|
|
|
@@ -255,11 +271,14 @@ async function pull({
|
|
|
255
271
|
};
|
|
256
272
|
const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
|
|
257
273
|
for (const key of localKeys) {
|
|
258
|
-
var _phraseAltTranslation;
|
|
259
|
-
const phraseKey = core.getUniqueKey(key, loadedTranslation.namespace);
|
|
274
|
+
var _defaultValues$key$gl2, _phraseAltTranslation;
|
|
275
|
+
const phraseKey = (_defaultValues$key$gl2 = defaultValues[key].globalKey) !== null && _defaultValues$key$gl2 !== void 0 ? _defaultValues$key$gl2 : core.getUniqueKey(key, loadedTranslation.namespace);
|
|
260
276
|
const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
|
|
261
277
|
if (!phraseTranslationMessage) {
|
|
262
278
|
trace(`Missing translation. No translation for key ${key} in phrase as ${phraseKey} in language ${alternativeLanguage}.`);
|
|
279
|
+
if (errorOnNoGlobalKeyTranslation && defaultValues[key].globalKey) {
|
|
280
|
+
throw new Error(`Missing translation for global key ${key} in language ${alternativeLanguage}`);
|
|
281
|
+
}
|
|
263
282
|
continue;
|
|
264
283
|
}
|
|
265
284
|
altTranslations[key] = {
|
|
@@ -310,7 +329,7 @@ async function push({
|
|
|
310
329
|
}
|
|
311
330
|
} = loadedTranslation;
|
|
312
331
|
for (const localKey of Object.keys(localTranslations)) {
|
|
313
|
-
|
|
332
|
+
var _globalKey;
|
|
314
333
|
const {
|
|
315
334
|
tags = [],
|
|
316
335
|
...localTranslation
|
|
@@ -318,18 +337,23 @@ async function push({
|
|
|
318
337
|
if (language === config.devLanguage) {
|
|
319
338
|
localTranslation.tags = [...tags, ...sharedTags];
|
|
320
339
|
}
|
|
340
|
+
let globalKey;
|
|
341
|
+
if (loadedTranslation.languages[config.devLanguage][localKey].globalKey) {
|
|
342
|
+
globalKey = loadedTranslation.languages[config.devLanguage][localKey].globalKey;
|
|
343
|
+
}
|
|
344
|
+
const phraseKey = (_globalKey = globalKey) !== null && _globalKey !== void 0 ? _globalKey : core.getUniqueKey(localKey, loadedTranslation.namespace);
|
|
321
345
|
phraseTranslations[language][phraseKey] = localTranslation;
|
|
322
346
|
}
|
|
323
347
|
}
|
|
324
348
|
}
|
|
325
349
|
const {
|
|
326
|
-
|
|
350
|
+
devLanguageUploadId
|
|
327
351
|
} = await pushTranslations(phraseTranslations, {
|
|
328
352
|
devLanguage: config.devLanguage,
|
|
329
353
|
branch
|
|
330
354
|
});
|
|
331
355
|
if (deleteUnusedKeys$1) {
|
|
332
|
-
await deleteUnusedKeys(
|
|
356
|
+
await deleteUnusedKeys(devLanguageUploadId, branch);
|
|
333
357
|
}
|
|
334
358
|
}
|
|
335
359
|
|
package/dist/vocab-phrase.esm.js
CHANGED
|
@@ -19,34 +19,43 @@ const log = (...params) => {
|
|
|
19
19
|
function translationsToCsv(translations, devLanguage) {
|
|
20
20
|
const languages = Object.keys(translations);
|
|
21
21
|
const altLanguages = languages.filter(language => language !== devLanguage);
|
|
22
|
-
// Ensure languages are ordered for locale mapping
|
|
23
|
-
const orderedLanguages = [devLanguage, ...altLanguages];
|
|
24
22
|
const devLanguageTranslations = translations[devLanguage];
|
|
25
|
-
const
|
|
23
|
+
const csvFilesByLanguage = Object.fromEntries(languages.map(language => [language, []]));
|
|
24
|
+
Object.entries(devLanguageTranslations).map(([key, {
|
|
26
25
|
message,
|
|
27
26
|
description,
|
|
28
27
|
tags
|
|
29
28
|
}]) => {
|
|
30
|
-
const
|
|
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 => {
|
|
31
33
|
var _translations$languag, _translations$languag2;
|
|
32
|
-
|
|
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
|
+
}
|
|
33
38
|
});
|
|
34
|
-
return [message, ...altTranslationMessages, key, description, tags === null || tags === void 0 ? void 0 : tags.join(',')];
|
|
35
|
-
});
|
|
36
|
-
const csvString = stringify(csv, {
|
|
37
|
-
delimiter: ',',
|
|
38
|
-
header: false
|
|
39
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
|
+
}));
|
|
40
49
|
|
|
41
50
|
// Column indices start at 1
|
|
42
|
-
const
|
|
43
|
-
const keyIndex = orderedLanguages.length + 1;
|
|
51
|
+
const keyIndex = 1;
|
|
44
52
|
const commentIndex = keyIndex + 1;
|
|
45
53
|
const tagColumn = commentIndex + 1;
|
|
54
|
+
const messageIndex = tagColumn + 1;
|
|
46
55
|
return {
|
|
47
|
-
|
|
48
|
-
localeMapping,
|
|
56
|
+
csvFileStrings,
|
|
49
57
|
keyIndex,
|
|
58
|
+
messageIndex,
|
|
50
59
|
commentIndex,
|
|
51
60
|
tagColumn
|
|
52
61
|
};
|
|
@@ -127,45 +136,50 @@ async function pushTranslations(translationsByLanguage, {
|
|
|
127
136
|
devLanguage,
|
|
128
137
|
branch
|
|
129
138
|
}) {
|
|
130
|
-
const formData = new FormData();
|
|
131
139
|
const {
|
|
132
|
-
|
|
133
|
-
localeMapping,
|
|
140
|
+
csvFileStrings,
|
|
134
141
|
keyIndex,
|
|
135
142
|
commentIndex,
|
|
136
|
-
tagColumn
|
|
143
|
+
tagColumn,
|
|
144
|
+
messageIndex
|
|
137
145
|
} = translationsToCsv(translationsByLanguage, devLanguage);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
formData.append(
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
+
}
|
|
166
180
|
}
|
|
167
181
|
return {
|
|
168
|
-
|
|
182
|
+
devLanguageUploadId
|
|
169
183
|
};
|
|
170
184
|
}
|
|
171
185
|
async function deleteUnusedKeys(uploadId, branch) {
|
|
@@ -198,7 +212,8 @@ async function ensureBranch(branch) {
|
|
|
198
212
|
}
|
|
199
213
|
|
|
200
214
|
async function pull({
|
|
201
|
-
branch = 'local-development'
|
|
215
|
+
branch = 'local-development',
|
|
216
|
+
errorOnNoGlobalKeyTranslation
|
|
202
217
|
}, config) {
|
|
203
218
|
trace(`Pulling translations from branch ${branch}`);
|
|
204
219
|
await ensureBranch(branch);
|
|
@@ -225,9 +240,10 @@ async function pull({
|
|
|
225
240
|
};
|
|
226
241
|
const localKeys = Object.keys(defaultValues);
|
|
227
242
|
for (const key of localKeys) {
|
|
243
|
+
var _defaultValues$key$gl;
|
|
228
244
|
defaultValues[key] = {
|
|
229
245
|
...defaultValues[key],
|
|
230
|
-
...allPhraseTranslations[config.devLanguage][getUniqueKey(key, loadedTranslation.namespace)]
|
|
246
|
+
...allPhraseTranslations[config.devLanguage][(_defaultValues$key$gl = defaultValues[key].globalKey) !== null && _defaultValues$key$gl !== void 0 ? _defaultValues$key$gl : getUniqueKey(key, loadedTranslation.namespace)]
|
|
231
247
|
};
|
|
232
248
|
}
|
|
233
249
|
|
|
@@ -243,11 +259,14 @@ async function pull({
|
|
|
243
259
|
};
|
|
244
260
|
const phraseAltTranslations = allPhraseTranslations[alternativeLanguage];
|
|
245
261
|
for (const key of localKeys) {
|
|
246
|
-
var _phraseAltTranslation;
|
|
247
|
-
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);
|
|
248
264
|
const phraseTranslationMessage = (_phraseAltTranslation = phraseAltTranslations[phraseKey]) === null || _phraseAltTranslation === void 0 ? void 0 : _phraseAltTranslation.message;
|
|
249
265
|
if (!phraseTranslationMessage) {
|
|
250
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
|
+
}
|
|
251
270
|
continue;
|
|
252
271
|
}
|
|
253
272
|
altTranslations[key] = {
|
|
@@ -298,7 +317,7 @@ async function push({
|
|
|
298
317
|
}
|
|
299
318
|
} = loadedTranslation;
|
|
300
319
|
for (const localKey of Object.keys(localTranslations)) {
|
|
301
|
-
|
|
320
|
+
var _globalKey;
|
|
302
321
|
const {
|
|
303
322
|
tags = [],
|
|
304
323
|
...localTranslation
|
|
@@ -306,18 +325,23 @@ async function push({
|
|
|
306
325
|
if (language === config.devLanguage) {
|
|
307
326
|
localTranslation.tags = [...tags, ...sharedTags];
|
|
308
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);
|
|
309
333
|
phraseTranslations[language][phraseKey] = localTranslation;
|
|
310
334
|
}
|
|
311
335
|
}
|
|
312
336
|
}
|
|
313
337
|
const {
|
|
314
|
-
|
|
338
|
+
devLanguageUploadId
|
|
315
339
|
} = await pushTranslations(phraseTranslations, {
|
|
316
340
|
devLanguage: config.devLanguage,
|
|
317
341
|
branch
|
|
318
342
|
});
|
|
319
343
|
if (deleteUnusedKeys$1) {
|
|
320
|
-
await deleteUnusedKeys(
|
|
344
|
+
await deleteUnusedKeys(devLanguageUploadId, branch);
|
|
321
345
|
}
|
|
322
346
|
}
|
|
323
347
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vocab/phrase",
|
|
3
|
-
"version": "0.0.0-
|
|
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": "0.0.0-
|
|
10
|
-
"@vocab/types": "^1.1.2",
|
|
9
|
+
"@vocab/core": "0.0.0-global-key-support-20231025223328",
|
|
11
10
|
"chalk": "^4.1.0",
|
|
12
11
|
"csv-stringify": "^6.2.3",
|
|
13
12
|
"debug": "^4.3.1",
|