@logto/cli 1.10.1 → 1.12.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.
|
@@ -29,7 +29,7 @@ export const translate = async ({ api, targetLanguage, sourceFilePath, extraProm
|
|
|
29
29
|
const response = await trySafe(api
|
|
30
30
|
.post('chat/completions', {
|
|
31
31
|
json: {
|
|
32
|
-
model: 'gpt-3.5-turbo',
|
|
32
|
+
model: 'gpt-3.5-turbo-1106',
|
|
33
33
|
messages: getTranslationPromptMessages({
|
|
34
34
|
sourceFileContent,
|
|
35
35
|
targetLanguage,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
type FileStructure = {
|
|
2
|
-
[key: string]: {
|
|
2
|
+
[key: string | number]: {
|
|
3
3
|
filePath?: string;
|
|
4
4
|
structure: FileStructure;
|
|
5
5
|
};
|
|
6
6
|
};
|
|
7
7
|
type NestedPhraseObject = {
|
|
8
|
-
[key: string]: [phrase: string, isTranslated: boolean] | NestedPhraseObject;
|
|
8
|
+
[key: string | number]: [phrase: string, isTranslated: boolean] | NestedPhraseObject;
|
|
9
9
|
};
|
|
10
10
|
type ParsedTuple = readonly [NestedPhraseObject, FileStructure];
|
|
11
11
|
/**
|
|
@@ -4,6 +4,28 @@ import path from 'node:path';
|
|
|
4
4
|
import { tryThat } from '@silverhand/essentials';
|
|
5
5
|
import ts from 'typescript';
|
|
6
6
|
import { consoleLog } from '../../../utils.js';
|
|
7
|
+
const getValue = (property) => {
|
|
8
|
+
if (ts.isStringLiteral(property.initializer) ||
|
|
9
|
+
ts.isNoSubstitutionTemplateLiteral(property.initializer)) {
|
|
10
|
+
return property.initializer.getText();
|
|
11
|
+
}
|
|
12
|
+
consoleLog.fatal('Unsupported property:', property.getFullText());
|
|
13
|
+
};
|
|
14
|
+
const hasLeadingUntranslatedComment = (fullText) => {
|
|
15
|
+
const commentRanges = ts.getLeadingCommentRanges(fullText, 0);
|
|
16
|
+
if (commentRanges?.[0]) {
|
|
17
|
+
if (commentRanges.length > 1) {
|
|
18
|
+
consoleLog.fatal('Multiple comments found for property.');
|
|
19
|
+
}
|
|
20
|
+
const commentRange = commentRanges[0];
|
|
21
|
+
const comment = fullText.slice(commentRange.pos, commentRange.end);
|
|
22
|
+
if (comment.includes(untranslatedMark)) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
consoleLog.warn('Unsupported comment:', comment);
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
};
|
|
7
29
|
const untranslatedMark = 'UNTRANSLATED';
|
|
8
30
|
/**
|
|
9
31
|
* Given a entrypoint file path of a language, parse the nested object of
|
|
@@ -94,33 +116,27 @@ export const parseLocaleFiles = (filePath) => {
|
|
|
94
116
|
fileStructure[key] = { structure };
|
|
95
117
|
/* eslint-enable @silverhand/fp/no-mutation */
|
|
96
118
|
}
|
|
97
|
-
else if (ts.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
const commentRange = commentRanges[0];
|
|
106
|
-
const comment = property.getFullText().slice(commentRange.pos, commentRange.end);
|
|
107
|
-
if (comment.includes(untranslatedMark)) {
|
|
108
|
-
// eslint-disable-next-line @silverhand/fp/no-mutation
|
|
109
|
-
nestedObject[key] = [value, false];
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
// eslint-disable-next-line @silverhand/fp/no-mutation
|
|
113
|
-
nestedObject[key] = [value, true];
|
|
114
|
-
consoleLog.warn('Unsupported comment:', comment);
|
|
119
|
+
else if (ts.isArrayLiteralExpression(property.initializer)) {
|
|
120
|
+
const elements = property.initializer.elements.map((element) => {
|
|
121
|
+
if (ts.isStringLiteralLike(element)) {
|
|
122
|
+
return [
|
|
123
|
+
[element.getText(), !hasLeadingUntranslatedComment(element.getFullText())],
|
|
124
|
+
{},
|
|
125
|
+
];
|
|
115
126
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
return traverseNode(element, {}, {});
|
|
128
|
+
});
|
|
129
|
+
/* eslint-disable @silverhand/fp/no-mutation */
|
|
130
|
+
nestedObject[key] = Object.fromEntries(elements.map(([phrases], index) => [index, phrases]));
|
|
131
|
+
fileStructure[key] = {
|
|
132
|
+
structure: Object.fromEntries(elements.map(([, structure], index) => [index, { structure }])),
|
|
133
|
+
};
|
|
134
|
+
/* eslint-enable @silverhand/fp/no-mutation */
|
|
121
135
|
}
|
|
122
136
|
else {
|
|
123
|
-
|
|
137
|
+
const value = getValue(property);
|
|
138
|
+
// eslint-disable-next-line @silverhand/fp/no-mutation
|
|
139
|
+
nestedObject[key] = [value, !hasLeadingUntranslatedComment(property.getFullText())];
|
|
124
140
|
}
|
|
125
141
|
}
|
|
126
142
|
};
|
|
@@ -210,10 +226,13 @@ const traverseNode = async (baseline, targetObject, targetFilePath, isRoot = fal
|
|
|
210
226
|
await fs.appendFile(targetFilePath, `const ${identifier} = {\n`);
|
|
211
227
|
// Recursively traverse the nested object of phrases and the file structure
|
|
212
228
|
// of the baseline language
|
|
229
|
+
// eslint-disable-next-line complexity
|
|
213
230
|
const traverseObject = async (baseline, targetObject, tabSize) => {
|
|
214
231
|
const [baselineObject, baselineStructure] = baseline;
|
|
232
|
+
const isBaselineArray = 0 in baselineObject;
|
|
215
233
|
for (const [key, value] of Object.entries(baselineObject)) {
|
|
216
234
|
const existingValue = targetObject[key];
|
|
235
|
+
const keyOutput = isBaselineArray ? '' : `${key}: `;
|
|
217
236
|
if (Array.isArray(value)) {
|
|
218
237
|
const [phrase] = value;
|
|
219
238
|
// If the key exists in the target language and the value is a translated
|
|
@@ -221,11 +240,11 @@ const traverseNode = async (baseline, targetObject, targetFilePath, isRoot = fal
|
|
|
221
240
|
// of the baseline language and add a comment to indicate that the phrase
|
|
222
241
|
// is untranslated to help identify missing translations.
|
|
223
242
|
if (Array.isArray(existingValue) && existingValue[1]) {
|
|
224
|
-
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}${
|
|
243
|
+
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}${keyOutput}${existingValue[0]},\n`);
|
|
225
244
|
}
|
|
226
245
|
else {
|
|
227
246
|
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}/** ${untranslatedMark} */\n`);
|
|
228
|
-
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}${
|
|
247
|
+
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}${keyOutput}${phrase},\n`);
|
|
229
248
|
}
|
|
230
249
|
}
|
|
231
250
|
// Not a string, treat it as a nested object or an import
|
|
@@ -236,11 +255,12 @@ const traverseNode = async (baseline, targetObject, targetFilePath, isRoot = fal
|
|
|
236
255
|
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}${key},\n`);
|
|
237
256
|
await traverseNode([value, keyStructure.structure], Array.isArray(existingValue) ? {} : existingValue ?? {}, path.join(targetDirectory, keyStructure.filePath));
|
|
238
257
|
}
|
|
239
|
-
// Otherwise, treat it as a nested object.
|
|
258
|
+
// Otherwise, treat it as a nested object or array.
|
|
240
259
|
else {
|
|
241
|
-
|
|
260
|
+
const isValueArray = 0 in value;
|
|
261
|
+
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}${keyOutput}${isValueArray ? '[' : '{'}\n`);
|
|
242
262
|
await traverseObject([value, keyStructure?.structure ?? {}], Array.isArray(existingValue) ? {} : existingValue ?? {}, tabSize + 2);
|
|
243
|
-
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}},\n`);
|
|
263
|
+
await fs.appendFile(targetFilePath, `${' '.repeat(tabSize)}${isValueArray ? ']' : '}'},\n`);
|
|
244
264
|
}
|
|
245
265
|
}
|
|
246
266
|
}
|
|
@@ -8,7 +8,7 @@ const sync = {
|
|
|
8
8
|
command: ['sync'],
|
|
9
9
|
describe: 'Translate all untranslated phrases using ChatGPT. Note the environment variable `OPENAI_API_KEY` is required to work.',
|
|
10
10
|
handler: async ({ path: inputPath }) => {
|
|
11
|
-
const queue = new PQueue({ concurrency:
|
|
11
|
+
const queue = new PQueue({ concurrency: 5 });
|
|
12
12
|
const instancePath = await inquireInstancePath(inputPath);
|
|
13
13
|
for (const languageTag of Object.keys(languages)) {
|
|
14
14
|
if (languageTag === baseLanguage) {
|
package/lib/package-json.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const packageJson = {
|
|
2
2
|
"name": "@logto/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Logto CLI.",
|
|
5
5
|
"author": "Silverhand Inc. <contact@silverhand.io>",
|
|
6
6
|
"homepage": "https://github.com/logto-io/logto#readme",
|
|
@@ -44,11 +44,11 @@ export const packageJson = {
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@logto/connector-kit": "workspace:^2.0.0",
|
|
47
|
-
"@logto/core-kit": "workspace:^2.2.
|
|
47
|
+
"@logto/core-kit": "workspace:^2.2.1",
|
|
48
48
|
"@logto/language-kit": "workspace:^1.0.0",
|
|
49
|
-
"@logto/phrases": "workspace:^1.
|
|
50
|
-
"@logto/phrases-experience": "workspace:^1.
|
|
51
|
-
"@logto/schemas": "workspace:1.
|
|
49
|
+
"@logto/phrases": "workspace:^1.8.0",
|
|
50
|
+
"@logto/phrases-experience": "workspace:^1.5.0",
|
|
51
|
+
"@logto/schemas": "workspace:1.12.0",
|
|
52
52
|
"@logto/shared": "workspace:^3.0.0",
|
|
53
53
|
"@silverhand/essentials": "^2.8.4",
|
|
54
54
|
"chalk": "^5.0.0",
|
|
@@ -71,7 +71,7 @@ export const packageJson = {
|
|
|
71
71
|
"tar": "^6.1.11",
|
|
72
72
|
"typescript": "^5.0.0",
|
|
73
73
|
"yargs": "^17.6.0",
|
|
74
|
-
"zod": "^3.22.
|
|
74
|
+
"zod": "^3.22.4"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@silverhand/eslint-config": "4.0.1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logto/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Logto CLI.",
|
|
5
5
|
"author": "Silverhand Inc. <contact@silverhand.io>",
|
|
6
6
|
"homepage": "https://github.com/logto-io/logto#readme",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@logto/connector-kit": "^2.0.0",
|
|
32
|
-
"@logto/core-kit": "^2.2.
|
|
32
|
+
"@logto/core-kit": "^2.2.1",
|
|
33
33
|
"@logto/language-kit": "^1.0.0",
|
|
34
|
-
"@logto/phrases": "^1.
|
|
35
|
-
"@logto/phrases-experience": "^1.
|
|
36
|
-
"@logto/schemas": "1.
|
|
34
|
+
"@logto/phrases": "^1.8.0",
|
|
35
|
+
"@logto/phrases-experience": "^1.5.0",
|
|
36
|
+
"@logto/schemas": "1.12.0",
|
|
37
37
|
"@logto/shared": "^3.0.0",
|
|
38
38
|
"@silverhand/essentials": "^2.8.4",
|
|
39
39
|
"chalk": "^5.0.0",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"tar": "^6.1.11",
|
|
57
57
|
"typescript": "^5.0.0",
|
|
58
58
|
"yargs": "^17.6.0",
|
|
59
|
-
"zod": "^3.22.
|
|
59
|
+
"zod": "^3.22.4"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@silverhand/eslint-config": "4.0.1",
|