@questlang/mcp-server 0.1.2 → 0.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/SKILL.md +8 -1
- package/dist/exporters.d.ts +14 -0
- package/dist/exporters.js +257 -0
- package/dist/exporters.js.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/save.d.ts +10 -0
- package/dist/tools/save.js +28 -0
- package/dist/tools/save.js.map +1 -0
- package/dist/tools/status.js +1 -7
- package/dist/tools/status.js.map +1 -1
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -45,7 +45,14 @@ After the user confirms:
|
|
|
45
45
|
2. Report the progress percentage to the user
|
|
46
46
|
3. If not complete, wait another 15 seconds and check again
|
|
47
47
|
4. Repeat until the order is complete or fails
|
|
48
|
-
|
|
48
|
+
|
|
49
|
+
### Step 6: Save translated files
|
|
50
|
+
|
|
51
|
+
When the order is complete, use `questlang_save_translation` with:
|
|
52
|
+
- The order ID from Step 4
|
|
53
|
+
- The original file path from Step 2
|
|
54
|
+
- This automatically converts from CSV back to the original format (ARB, JSON, Android XML, iOS .strings, PO, XLIFF) and writes the output file(s)
|
|
55
|
+
- Report the created file paths to the user
|
|
49
56
|
|
|
50
57
|
## Tips
|
|
51
58
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function languageToLocale(language: string): string;
|
|
2
|
+
/**
|
|
3
|
+
* Parse the translated CSV returned by the backend.
|
|
4
|
+
* Returns a map of language -> (key -> translated value).
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseTranslatedCsv(csv: string): {
|
|
7
|
+
languages: string[];
|
|
8
|
+
translations: Map<string, Map<string, string>>;
|
|
9
|
+
};
|
|
10
|
+
export declare function exportToOriginalFormat(originalFilePath: string, translations: Map<string, string>, language: string): Promise<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Generate output filename based on original path and target language.
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateOutputPath(originalFilePath: string, language: string): string;
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
const LANGUAGE_TO_LOCALE = {
|
|
3
|
+
'English': 'en',
|
|
4
|
+
'Russian': 'ru',
|
|
5
|
+
'Spanish': 'es',
|
|
6
|
+
'French': 'fr',
|
|
7
|
+
'German': 'de',
|
|
8
|
+
'Chinese (Simplified)': 'zh',
|
|
9
|
+
'Chinese (Traditional)': 'zh_TW',
|
|
10
|
+
'Japanese': 'ja',
|
|
11
|
+
'Korean': 'ko',
|
|
12
|
+
'Arabic': 'ar',
|
|
13
|
+
'Portuguese': 'pt',
|
|
14
|
+
'Italian': 'it',
|
|
15
|
+
'Turkish': 'tr',
|
|
16
|
+
'Hindi': 'hi',
|
|
17
|
+
'Dutch': 'nl',
|
|
18
|
+
'Polish': 'pl',
|
|
19
|
+
'Swedish': 'sv',
|
|
20
|
+
'Greek': 'el',
|
|
21
|
+
'Hebrew': 'he',
|
|
22
|
+
'Indonesian': 'id',
|
|
23
|
+
'Thai': 'th',
|
|
24
|
+
};
|
|
25
|
+
export function languageToLocale(language) {
|
|
26
|
+
return LANGUAGE_TO_LOCALE[language] || language.toLowerCase().slice(0, 2);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Strip CSV formula injection protection (leading ' before +, -, =, @)
|
|
30
|
+
*/
|
|
31
|
+
function stripFormulaProtection(value) {
|
|
32
|
+
if (value.length > 1 && value[0] === "'" && /^[+\-=@]/.test(value[1])) {
|
|
33
|
+
return value.slice(1);
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Parse the translated CSV returned by the backend.
|
|
39
|
+
* Returns a map of language -> (key -> translated value).
|
|
40
|
+
*/
|
|
41
|
+
export function parseTranslatedCsv(csv) {
|
|
42
|
+
const lines = [];
|
|
43
|
+
let current = '';
|
|
44
|
+
let inQuotes = false;
|
|
45
|
+
for (let i = 0; i < csv.length; i++) {
|
|
46
|
+
const ch = csv[i];
|
|
47
|
+
if (ch === '"') {
|
|
48
|
+
if (inQuotes && csv[i + 1] === '"') {
|
|
49
|
+
current += '"';
|
|
50
|
+
i++;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
inQuotes = !inQuotes;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if ((ch === '\n' || ch === '\r') && !inQuotes) {
|
|
57
|
+
if (current.length > 0)
|
|
58
|
+
lines.push(current);
|
|
59
|
+
current = '';
|
|
60
|
+
if (ch === '\r' && csv[i + 1] === '\n')
|
|
61
|
+
i++;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
current += ch;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (current.length > 0)
|
|
68
|
+
lines.push(current);
|
|
69
|
+
if (lines.length === 0)
|
|
70
|
+
return { languages: [], translations: new Map() };
|
|
71
|
+
// Parse header
|
|
72
|
+
const header = parseCsvRow(lines[0]);
|
|
73
|
+
// header: ["ID", "Original Text", "Spanish", "French", ...]
|
|
74
|
+
const languages = header.slice(2);
|
|
75
|
+
const translations = new Map();
|
|
76
|
+
for (const lang of languages) {
|
|
77
|
+
translations.set(lang, new Map());
|
|
78
|
+
}
|
|
79
|
+
for (let i = 1; i < lines.length; i++) {
|
|
80
|
+
const row = parseCsvRow(lines[i]);
|
|
81
|
+
if (row.length < 3)
|
|
82
|
+
continue;
|
|
83
|
+
const key = row[0];
|
|
84
|
+
for (let j = 0; j < languages.length; j++) {
|
|
85
|
+
const value = row[j + 2] ?? '';
|
|
86
|
+
translations.get(languages[j]).set(key, stripFormulaProtection(value));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { languages, translations };
|
|
90
|
+
}
|
|
91
|
+
function parseCsvRow(line) {
|
|
92
|
+
const fields = [];
|
|
93
|
+
let current = '';
|
|
94
|
+
let inQuotes = false;
|
|
95
|
+
for (let i = 0; i < line.length; i++) {
|
|
96
|
+
const ch = line[i];
|
|
97
|
+
if (ch === '"') {
|
|
98
|
+
if (inQuotes && line[i + 1] === '"') {
|
|
99
|
+
current += '"';
|
|
100
|
+
i++;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
inQuotes = !inQuotes;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (ch === ',' && !inQuotes) {
|
|
107
|
+
fields.push(current);
|
|
108
|
+
current = '';
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
current += ch;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
fields.push(current);
|
|
115
|
+
return fields;
|
|
116
|
+
}
|
|
117
|
+
// --- Format exporters ---
|
|
118
|
+
export async function exportToOriginalFormat(originalFilePath, translations, language) {
|
|
119
|
+
const ext = originalFilePath.slice(originalFilePath.lastIndexOf('.')).toLowerCase();
|
|
120
|
+
const originalContent = await readFile(originalFilePath, 'utf-8');
|
|
121
|
+
switch (ext) {
|
|
122
|
+
case '.arb':
|
|
123
|
+
return exportArb(originalContent, translations, language);
|
|
124
|
+
case '.json':
|
|
125
|
+
return exportJson(originalContent, translations);
|
|
126
|
+
case '.xml':
|
|
127
|
+
return exportAndroidXml(translations);
|
|
128
|
+
case '.strings':
|
|
129
|
+
return exportIosStrings(translations);
|
|
130
|
+
case '.po':
|
|
131
|
+
case '.pot':
|
|
132
|
+
return exportPo(translations);
|
|
133
|
+
case '.xliff':
|
|
134
|
+
case '.xlf':
|
|
135
|
+
return exportXliff(translations, language);
|
|
136
|
+
default:
|
|
137
|
+
return exportCsvFallback(translations);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function exportArb(originalContent, translations, language) {
|
|
141
|
+
const original = JSON.parse(originalContent);
|
|
142
|
+
const locale = languageToLocale(language);
|
|
143
|
+
const result = { '@@locale': locale };
|
|
144
|
+
for (const key of Object.keys(original)) {
|
|
145
|
+
if (key === '@@locale')
|
|
146
|
+
continue;
|
|
147
|
+
if (key.startsWith('@')) {
|
|
148
|
+
// Copy metadata as-is
|
|
149
|
+
result[key] = original[key];
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// Use translation if available, else keep original
|
|
153
|
+
result[key] = translations.get(key) ?? original[key];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return JSON.stringify(result, null, 2) + '\n';
|
|
157
|
+
}
|
|
158
|
+
function exportJson(originalContent, translations) {
|
|
159
|
+
const original = JSON.parse(originalContent);
|
|
160
|
+
function rebuild(obj, prefix = '') {
|
|
161
|
+
const result = {};
|
|
162
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
163
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
164
|
+
if (typeof value === 'string') {
|
|
165
|
+
result[key] = translations.get(fullKey) ?? value;
|
|
166
|
+
}
|
|
167
|
+
else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
168
|
+
result[key] = rebuild(value, fullKey);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
result[key] = value;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
return JSON.stringify(rebuild(original), null, 2) + '\n';
|
|
177
|
+
}
|
|
178
|
+
function exportAndroidXml(translations) {
|
|
179
|
+
let xml = '<?xml version="1.0" encoding="utf-8"?>\n<resources>\n';
|
|
180
|
+
for (const [key, value] of translations) {
|
|
181
|
+
const escaped = value
|
|
182
|
+
.replace(/&/g, '&')
|
|
183
|
+
.replace(/</g, '<')
|
|
184
|
+
.replace(/>/g, '>')
|
|
185
|
+
.replace(/'/g, "\\'")
|
|
186
|
+
.replace(/"/g, '\\"');
|
|
187
|
+
xml += ` <string name="${key}">${escaped}</string>\n`;
|
|
188
|
+
}
|
|
189
|
+
xml += '</resources>\n';
|
|
190
|
+
return xml;
|
|
191
|
+
}
|
|
192
|
+
function exportIosStrings(translations) {
|
|
193
|
+
let output = '';
|
|
194
|
+
for (const [key, value] of translations) {
|
|
195
|
+
const escapedKey = key.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
196
|
+
const escapedValue = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
197
|
+
output += `"${escapedKey}" = "${escapedValue}";\n`;
|
|
198
|
+
}
|
|
199
|
+
return output;
|
|
200
|
+
}
|
|
201
|
+
function exportPo(translations) {
|
|
202
|
+
let output = '';
|
|
203
|
+
for (const [key, value] of translations) {
|
|
204
|
+
const escapedKey = key.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
205
|
+
const escapedValue = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
206
|
+
output += `msgid "${escapedKey}"\nmsgstr "${escapedValue}"\n\n`;
|
|
207
|
+
}
|
|
208
|
+
return output;
|
|
209
|
+
}
|
|
210
|
+
function exportXliff(translations, language) {
|
|
211
|
+
const locale = languageToLocale(language);
|
|
212
|
+
let xml = `<?xml version="1.0" encoding="UTF-8"?>\n`;
|
|
213
|
+
xml += `<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">\n`;
|
|
214
|
+
xml += ` <file source-language="en" target-language="${locale}" datatype="plaintext">\n`;
|
|
215
|
+
xml += ` <body>\n`;
|
|
216
|
+
for (const [key, value] of translations) {
|
|
217
|
+
const escaped = value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
218
|
+
xml += ` <trans-unit id="${key}">\n`;
|
|
219
|
+
xml += ` <target>${escaped}</target>\n`;
|
|
220
|
+
xml += ` </trans-unit>\n`;
|
|
221
|
+
}
|
|
222
|
+
xml += ` </body>\n </file>\n</xliff>\n`;
|
|
223
|
+
return xml;
|
|
224
|
+
}
|
|
225
|
+
function exportCsvFallback(translations) {
|
|
226
|
+
let output = '';
|
|
227
|
+
for (const [key, value] of translations) {
|
|
228
|
+
const ek = key.includes(',') || key.includes('"') ? `"${key.replace(/"/g, '""')}"` : key;
|
|
229
|
+
const ev = value.includes(',') || value.includes('"') ? `"${value.replace(/"/g, '""')}"` : value;
|
|
230
|
+
output += `${ek},${ev}\n`;
|
|
231
|
+
}
|
|
232
|
+
return output;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Generate output filename based on original path and target language.
|
|
236
|
+
*/
|
|
237
|
+
export function generateOutputPath(originalFilePath, language) {
|
|
238
|
+
const locale = languageToLocale(language);
|
|
239
|
+
const dir = originalFilePath.slice(0, originalFilePath.lastIndexOf('/'));
|
|
240
|
+
const filename = originalFilePath.slice(originalFilePath.lastIndexOf('/') + 1);
|
|
241
|
+
const ext = filename.slice(filename.lastIndexOf('.'));
|
|
242
|
+
const base = filename.slice(0, filename.lastIndexOf('.'));
|
|
243
|
+
// ARB: intl_ru.arb → intl_es.arb
|
|
244
|
+
// JSON: en.json → es.json, messages_en.json → messages_es.json
|
|
245
|
+
const localePattern = /^(.*)(?:_[a-z]{2}(?:[-_][A-Z]{2})?|[a-z]{2}(?:[-_][A-Z]{2})?)$/;
|
|
246
|
+
const match = base.match(localePattern);
|
|
247
|
+
if (match) {
|
|
248
|
+
const prefix = match[1];
|
|
249
|
+
if (prefix) {
|
|
250
|
+
return `${dir}/${prefix}${locale}${ext}`;
|
|
251
|
+
}
|
|
252
|
+
return `${dir}/${locale}${ext}`;
|
|
253
|
+
}
|
|
254
|
+
// Fallback: append locale before extension
|
|
255
|
+
return `${dir}/${base}_${locale}${ext}`;
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=exporters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporters.js","sourceRoot":"","sources":["../src/exporters.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import { getOrderStatus } from './tools/status.js';
|
|
|
16
16
|
import { listOrders } from './tools/orders.js';
|
|
17
17
|
import { updateGlossary } from './tools/glossary.js';
|
|
18
18
|
import { requestQualityReview, getReviewReport } from './tools/review.js';
|
|
19
|
+
import { saveTranslation } from './tools/save.js';
|
|
19
20
|
const apiKey = process.env.QUESTLANG_API_KEY;
|
|
20
21
|
const baseUrl = process.env.QUESTLANG_BASE_URL || 'https://questlang.ru';
|
|
21
22
|
if (!apiKey) {
|
|
@@ -81,6 +82,14 @@ server.tool('questlang_update_glossary', 'Add a term to the translation glossary
|
|
|
81
82
|
const result = await updateGlossary(client, term, translations, type, context, inflections);
|
|
82
83
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
83
84
|
});
|
|
85
|
+
server.tool('questlang_save_translation', 'Save a completed translation back to the original file format. Downloads the translated CSV, converts it to the source format (JSON, ARB, Android XML, iOS .strings, PO, XLIFF), and writes the output file(s). Strips CSV formula protection characters.', {
|
|
86
|
+
orderId: z.string().describe('The order ID of the completed translation'),
|
|
87
|
+
originalFilePath: z.string().describe('Absolute path to the original source file (used to determine format and structure)'),
|
|
88
|
+
outputDir: z.string().optional().describe('Optional output directory. Defaults to the same directory as the original file.'),
|
|
89
|
+
}, async ({ orderId, originalFilePath, outputDir }) => {
|
|
90
|
+
const result = await saveTranslation(client, orderId, originalFilePath, outputDir);
|
|
91
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
92
|
+
});
|
|
84
93
|
server.tool('questlang_request_review', 'Request an AI quality review for a completed translation order. Costs ~30% of original translation cost.', {
|
|
85
94
|
orderId: z.string().describe('The order ID returned from questlang_translate_file'),
|
|
86
95
|
model: z.string().optional().describe('Review model (e.g. "claude-haiku-4-5-20251001", "claude-sonnet-4-5-20250929")'),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;IAC/B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,IAAI,EAAE,CAAC;IACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { QuestlangClient } from '../client.js';
|
|
2
|
+
interface SaveResult {
|
|
3
|
+
files: Array<{
|
|
4
|
+
language: string;
|
|
5
|
+
path: string;
|
|
6
|
+
}>;
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function saveTranslation(client: QuestlangClient, orderId: string, originalFilePath: string, outputDir?: string): Promise<SaveResult>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { writeFile } from 'node:fs/promises';
|
|
2
|
+
import { parseTranslatedCsv, exportToOriginalFormat, generateOutputPath } from '../exporters.js';
|
|
3
|
+
export async function saveTranslation(client, orderId, originalFilePath, outputDir) {
|
|
4
|
+
// Download translated CSV
|
|
5
|
+
const csv = await client.downloadOrder(orderId);
|
|
6
|
+
const { languages, translations } = parseTranslatedCsv(csv);
|
|
7
|
+
if (languages.length === 0) {
|
|
8
|
+
throw new Error('No translations found in the order');
|
|
9
|
+
}
|
|
10
|
+
const files = [];
|
|
11
|
+
for (const language of languages) {
|
|
12
|
+
const langTranslations = translations.get(language);
|
|
13
|
+
const content = await exportToOriginalFormat(originalFilePath, langTranslations, language);
|
|
14
|
+
let outputPath = generateOutputPath(originalFilePath, language);
|
|
15
|
+
if (outputDir) {
|
|
16
|
+
const filename = outputPath.slice(outputPath.lastIndexOf('/') + 1);
|
|
17
|
+
outputDir = outputDir.replace(/\/$/, '');
|
|
18
|
+
outputPath = `${outputDir}/${filename}`;
|
|
19
|
+
}
|
|
20
|
+
await writeFile(outputPath, content, 'utf-8');
|
|
21
|
+
files.push({ language, path: outputPath });
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
files,
|
|
25
|
+
message: `Saved ${files.length} translated file(s) in original format.`,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=save.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.js","sourceRoot":"","sources":["../../src/tools/save.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAOjG,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAuB,EACvB,OAAe,EACf,gBAAwB,EACxB,SAAkB;IAElB,0BAA0B;IAC1B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAE5D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,KAAK,GAA8C,EAAE,CAAC;IAE5D,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,gBAAgB,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;QACrD,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QAE3F,IAAI,UAAU,GAAG,kBAAkB,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QAChE,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACnE,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACzC,UAAU,GAAG,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC;QAC1C,CAAC;QAED,MAAM,SAAS,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,KAAK,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO;QACL,KAAK;QACL,OAAO,EAAE,SAAS,KAAK,CAAC,MAAM,yCAAyC;KACxE,CAAC;AACJ,CAAC"}
|
package/dist/tools/status.js
CHANGED
|
@@ -28,13 +28,7 @@ export async function getOrderStatus(client, orderId) {
|
|
|
28
28
|
result.qualityReviewStatus = order.qualityReviewStatus;
|
|
29
29
|
}
|
|
30
30
|
if (order.status === 'completed') {
|
|
31
|
-
|
|
32
|
-
const content = await client.downloadOrder(orderId);
|
|
33
|
-
result.translatedContent = content;
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
// Download failed, still return status
|
|
37
|
-
}
|
|
31
|
+
result.downloadUrl = `/api/orders/${orderId}/download`;
|
|
38
32
|
}
|
|
39
33
|
return result;
|
|
40
34
|
}
|
package/dist/tools/status.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAuB,EAAE,OAAe;IAC3E,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAiB;QAC3B,MAAM,EAAE,KAAK,CAAC,MAAgB;QAC9B,QAAQ,EAAE,CAAC,KAAK,CAAC,mBAAmB,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAW;KACvE,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAmD,CAAC;IACxE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;QAC9B,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,aAAuB,CAAC;IACxD,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAe,CAAC;IACvC,CAAC;IAED,+CAA+C;IAC/C,MAAM,gBAAgB,GAAG,KAAK,CAAC,gBAAuD,CAAC;IACvF,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,gBAAgB,CAAC,oBAA0C,CAAC;QAC/E,MAAM,UAAU,GAAG,gBAAgB,CAAC,gBAAsD,CAAC;QAC3F,IAAI,UAAU,IAAI,IAAI,IAAI,UAAU,EAAE,CAAC;YACrC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;iBAC7C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC;iBACzC,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,CAAC,iBAAiB,GAAG,GAAG,UAAU,uBAAuB,aAAa,GAAG,CAAC;QAClF,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;QAC9B,MAAM,CAAC,mBAAmB,GAAG,KAAK,CAAC,mBAA6B,CAAC;IACnE,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAuB,EAAE,OAAe;IAC3E,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAiB;QAC3B,MAAM,EAAE,KAAK,CAAC,MAAgB;QAC9B,QAAQ,EAAE,CAAC,KAAK,CAAC,mBAAmB,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAW;KACvE,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAmD,CAAC;IACxE,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC;QAC9B,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,aAAuB,CAAC;IACxD,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAe,CAAC;IACvC,CAAC;IAED,+CAA+C;IAC/C,MAAM,gBAAgB,GAAG,KAAK,CAAC,gBAAuD,CAAC;IACvF,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,gBAAgB,CAAC,oBAA0C,CAAC;QAC/E,MAAM,UAAU,GAAG,gBAAgB,CAAC,gBAAsD,CAAC;QAC3F,IAAI,UAAU,IAAI,IAAI,IAAI,UAAU,EAAE,CAAC;YACrC,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;iBAC7C,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,CAAC;iBACzC,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,CAAC,iBAAiB,GAAG,GAAG,UAAU,uBAAuB,aAAa,GAAG,CAAC;QAClF,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;QAC9B,MAAM,CAAC,mBAAmB,GAAG,KAAK,CAAC,mBAA6B,CAAC;IACnE,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,WAAW,GAAG,eAAe,OAAO,WAAW,CAAC;IACzD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@questlang/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server for AI-powered i18n file translation. Translates JSON, CSV, Android XML, iOS .strings, PO, and XLIFF into 20 languages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|