glotstack 0.0.4 → 0.0.7

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/cli.js CHANGED
@@ -1,5 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
3
26
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
27
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
28
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -20,12 +43,140 @@ const findConfig_1 = require("./util/findConfig");
20
43
  const process_1 = require("process");
21
44
  const object_1 = require("./util/object");
22
45
  const yaml_1 = require("./util/yaml");
46
+ const eslint_1 = __importDefault(require("eslint"));
47
+ const readline = __importStar(require("node:readline/promises"));
48
+ const node_process_1 = require("node:process");
49
+ const undici_1 = require("undici");
50
+ const undici_2 = require("undici");
51
+ const node_fs_1 = require("node:fs");
52
+ const promises_1 = require("node:fs/promises");
53
+ const node_path_1 = require("node:path");
54
+ const fetchGlotstack = function (url, apiKey, body, overrideHeaders) {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ console.info(`Extracting translations with: ${url}`);
57
+ const headers = Object.assign({ 'authorization': `Bearer ${apiKey}` }, (overrideHeaders == null ? {} : overrideHeaders));
58
+ let payloadBody;
59
+ if (!(body instanceof undici_2.FormData)) {
60
+ headers['content-type'] = 'application/json';
61
+ payloadBody = JSON.stringify(body);
62
+ }
63
+ else {
64
+ payloadBody = body;
65
+ }
66
+ try {
67
+ const res = yield (0, undici_1.fetch)(url, { method: 'POST', body: payloadBody, headers });
68
+ if (!res.ok)
69
+ throw new Error(`HTTP ${res.status}: ${res.statusText}`);
70
+ return res.json();
71
+ }
72
+ catch (err) {
73
+ console.error('Fetch failed:', err);
74
+ process.exit(1);
75
+ }
76
+ });
77
+ };
78
+ function unflatten(flat) {
79
+ const result = {};
80
+ for (const flatKey in flat) {
81
+ const parts = flatKey.split('.');
82
+ let current = result;
83
+ parts.forEach((part, idx) => {
84
+ if (idx === parts.length - 1) {
85
+ current[part] = flat[flatKey];
86
+ }
87
+ else {
88
+ if (!(part in current)) {
89
+ current[part] = {};
90
+ }
91
+ current = current[part];
92
+ }
93
+ });
94
+ }
95
+ return result;
96
+ }
97
+ function resolveConfigAndOptions(options) {
98
+ return __awaiter(this, void 0, void 0, function* () {
99
+ const configPath = (0, findConfig_1.findGlotstackConfig)((0, process_1.cwd)());
100
+ let config = {};
101
+ if (configPath != null) {
102
+ console.info('Loading config file at ', configPath);
103
+ try {
104
+ const text = yield fs_1.promises.readFile(configPath, 'utf-8');
105
+ config = JSON.parse(text);
106
+ console.info('Loaded config file', config);
107
+ }
108
+ catch (err) {
109
+ //pass
110
+ }
111
+ }
112
+ if ('outputLocales' in options) {
113
+ if (options.outputLocales.includes('en-US')) {
114
+ console.warn('en-US detected in outputLocales, removing');
115
+ options.outputLocales = options.outputLocales.filter((x) => x !== 'en-US');
116
+ }
117
+ }
118
+ return (0, object_1.merge)(config, options);
119
+ });
120
+ }
23
121
  function run(args) {
24
122
  return __awaiter(this, void 0, void 0, function* () {
123
+ var _a, _b;
124
+ commander_1.program
125
+ .command('extract-translations')
126
+ .description('extract translations from all compatible source files.')
127
+ .option('--source-path [path]', 'to source files root directory', '.')
128
+ .option('--api-origin [url]', 'glotstack api origin', (_a = process.env.GLOTSTACK_HOST) !== null && _a !== void 0 ? _a : 'https://glotstack.ai')
129
+ .option('--api-key [key]', 'api key for glotstack.ai')
130
+ .option('--yes', 'skip confirm checks', false)
131
+ .action((options) => __awaiter(this, void 0, void 0, function* () {
132
+ if (!options.apiOrigin) {
133
+ throw new Error('apiOrigin must be specified');
134
+ }
135
+ const linter = new eslint_1.default.ESLint({ overrideConfigFile: path_1.default.join(__dirname, '..', 'eslint-raw-string.mjs') });
136
+ const results = yield linter.lintFiles(["./**/*"]);
137
+ const filesWithIssues = results
138
+ .filter((r) => r.errorCount + r.warningCount > 0)
139
+ .map((r) => r.filePath);
140
+ const rl = readline.createInterface({ input: node_process_1.stdin, output: node_process_1.stdout });
141
+ const askToSend = () => __awaiter(this, void 0, void 0, function* () {
142
+ if (options.yes) {
143
+ return true;
144
+ }
145
+ const response = yield rl.question(`Your source are going to be sent to our LLM -- they should not contain any secrets. Proceed? (yes/no):`);
146
+ if (response === 'yes') {
147
+ return true;
148
+ }
149
+ else if (response !== 'no') {
150
+ console.error('Please respond with yes or no.');
151
+ return askToSend();
152
+ }
153
+ else {
154
+ return false;
155
+ }
156
+ });
157
+ const send = yield askToSend();
158
+ if (send) {
159
+ console.info('Sending files to LLM');
160
+ const url = `${options.apiOrigin}/uploads/translations/extract`;
161
+ const form = new undici_2.FormData();
162
+ for (let i = 0; i < filesWithIssues.length; i++) {
163
+ const filePath = filesWithIssues[i];
164
+ form.append(`file_${i}`, yield (0, node_fs_1.openAsBlob)(filePath), filePath);
165
+ console.debug(`Uploading file: ${filePath}`);
166
+ }
167
+ const data = yield fetchGlotstack(url, options.apiKey, form);
168
+ data.translations.map(elem => console.info(`${elem.name}:\n ${elem.modified_source.url}\n\n`));
169
+ rl.close();
170
+ }
171
+ else {
172
+ rl.close();
173
+ }
174
+ }));
25
175
  commander_1.program
26
176
  .command('get-translations')
177
+ .description('fetch translations for all [output-locals...]. Use .glotstack.json for repeatable results.')
27
178
  .option('--source-path [path]', 'path to en-US.json (or your canonical source json)')
28
- .option('--api-origin [url]', 'glotstack api origin', 'http://localhost:4001')
179
+ .option('--api-origin [url]', 'glotstack api origin', (_b = process.env.GLOTSTACK_HOST) !== null && _b !== void 0 ? _b : 'https://glotstack.ai')
29
180
  .option('--output-dir [path]', 'path to output directory')
30
181
  .option('--api-key [key]', 'api key for glotstack.ai')
31
182
  .option('--project-id [id]', '(optional) specific project to use')
@@ -44,24 +195,17 @@ function run(args) {
44
195
  //pass
45
196
  }
46
197
  }
47
- const resolved = (0, object_1.merge)(config, options, { outputLocales });
48
- const { apiOrigin, sourcePath, outputDir, projectId } = resolved;
49
- if (resolved.outputLocales.includes('en-US')) {
50
- console.warn('en-US detected in outputLocales, removing');
51
- resolved.outputLocales = resolved.outputLocales.filter((x) => x !== 'en-US');
52
- }
53
- if (!sourcePath) {
198
+ const resolved = yield resolveConfigAndOptions(Object.assign(Object.assign({}, options), { outputLocales: outputLocales }));
199
+ if (!resolved.sourcePath) {
54
200
  throw new Error('sourcePath must be specified');
55
201
  }
56
- if (!apiOrigin) {
202
+ if (!resolved.apiOrigin) {
57
203
  throw new Error('apiOrigin must be specified');
58
204
  }
59
- if (!outputDir) {
205
+ if (!resolved.outputDir) {
60
206
  throw new Error('outputDir must be specified');
61
207
  }
62
- const url = `${apiOrigin}/api/translations`;
63
- console.info(`Fetching translations from: ${url}`);
64
- const absPath = path_1.default.resolve(sourcePath);
208
+ const absPath = path_1.default.resolve(resolved.sourcePath);
65
209
  const fileContent = yield fs_1.promises.readFile(absPath, 'utf-8');
66
210
  let json = null;
67
211
  try {
@@ -76,28 +220,55 @@ function run(args) {
76
220
  throw err;
77
221
  }
78
222
  }
79
- const body = Object.assign({ locales: resolved.outputLocales, translations: json }, Object.assign({}, (projectId != null ? { projectId } : {})));
80
- const headers = {
81
- 'Content-Type': 'application/json',
82
- 'Authorization': `Bearer ${resolved.apiKey}`,
83
- };
84
- try {
85
- const res = yield fetch(url, { method: 'POST', body: JSON.stringify(body), headers });
86
- if (!res.ok)
87
- throw new Error(`HTTP ${res.status}: ${res.statusText}`);
88
- const data = yield res.json();
89
- console.info('Received translations:', data);
90
- Object.entries(data.data).map(([key, val]) => {
91
- const p = `${outputDir}/${key}.json`;
92
- console.info(`Writing file ${p}`);
93
- fs_1.promises.writeFile(`${outputDir}/${key}.json`, JSON.stringify(val, null, 2));
94
- });
95
- // fs.writeFile(`${outputDir}/source.json`, JSON.stringify(json, null, 2))
223
+ const body = Object.assign({ locales: resolved.outputLocales, translations: json }, Object.assign({}, (resolved.projectId != null ? { projectId: resolved.projectId } : {})));
224
+ const url = `${options.apiOrigin}/api/translations`;
225
+ const data = yield fetchGlotstack(url, resolved.apiKey, body);
226
+ console.info('Received translations:', data);
227
+ Object.entries(data.data).map(([key, val]) => {
228
+ const p = `${resolved.outputDir}/${key}.json`;
229
+ console.info(`Writing file ${p}`);
230
+ fs_1.promises.writeFile(`${resolved.outputDir}/${key}.json`, JSON.stringify(val, null, 2));
231
+ });
232
+ }));
233
+ commander_1.program
234
+ .command('format-json')
235
+ .description('format files in --source-path [path] to nested (not flat)')
236
+ .option('--source-path [path]', 'to source files root directory', '.')
237
+ .option('--yes', 'skip confirm checks', false)
238
+ .action((options) => __awaiter(this, void 0, void 0, function* () {
239
+ if (!options.sourcePath) {
240
+ throw new Error('sourcePath must be specified');
96
241
  }
97
- catch (err) {
98
- console.error('Fetch failed:', err);
99
- process.exit(1);
242
+ const rl = readline.createInterface({ input: node_process_1.stdin, output: node_process_1.stdout });
243
+ const askToSend = () => __awaiter(this, void 0, void 0, function* () {
244
+ if (options.yes) {
245
+ return true;
246
+ }
247
+ const response = yield rl.question(`This will update your source files -- have you checked them into SCM/git? Type yes to proceed (yes/no):`);
248
+ if (response === 'yes') {
249
+ return true;
250
+ }
251
+ else if (response !== 'no') {
252
+ console.error('Please respond with yes or no.');
253
+ return askToSend();
254
+ }
255
+ else {
256
+ return false;
257
+ }
258
+ });
259
+ const yes = yield askToSend();
260
+ if (yes) {
261
+ const files = yield (0, promises_1.readdir)(options.sourcePath);
262
+ for (let i = 0; i < (yield files).length; i++) {
263
+ const fp = (0, node_path_1.resolve)(options.sourcePath, files[i]);
264
+ const text = yield (0, promises_1.readFile)(fp, 'utf-8');
265
+ const json = JSON.parse(text);
266
+ const formatted = JSON.stringify(unflatten(json), null, 2);
267
+ yield (0, promises_1.writeFile)(fp, formatted);
268
+ }
269
+ rl.close();
100
270
  }
271
+ rl.close();
101
272
  }));
102
273
  yield commander_1.program.parseAsync(args);
103
274
  });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAA4C;AAC5C,gDAAuB;AACvB,2BAAqD;AACrD,kDAAuD;AACvD,qCAA6B;AAC7B,0CAAqC;AACrC,sCAAsC;AACtC,oDAA2B;AAC3B,iEAAkD;AAClD,+CAA+D;AAE/D,mCAA8B;AAC9B,mCAAiC;AACjC,qCAAoC;AACpC,+CAA+D;AAC/D,yCAAmC;AAEnC,MAAM,cAAc,GAAG,UAAmB,GAAW,EAAE,MAAc,EAAE,IAAoC,EAAE,eAAqC;;QAChJ,OAAO,CAAC,IAAI,CAAC,iCAAiC,GAAG,EAAE,CAAC,CAAA;QAEpD,MAAM,OAAO,mBACX,eAAe,EAAE,UAAU,MAAM,EAAE,IAChC,CAAC,eAAe,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CACpD,CAAA;QAED,IAAI,WAA8B,CAAA;QAElC,IAAI,CAAC,CAAC,IAAI,YAAY,iBAAQ,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAA;YAC5C,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QACpC,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,IAAI,CAAA;QACpB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAA,cAAK,EAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAA;YAC5E,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,CAAA;YACrE,OAAO,GAAG,CAAC,IAAI,EAAO,CAAA;QACxB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,CAAC,CAAA;YACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;CAAA,CAAA;AAED,SAAS,SAAS,CAAC,IAAyB;IAC1C,MAAM,MAAM,GAAwB,EAAE,CAAA;IAEtC,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAChC,IAAI,OAAO,GAAG,MAAM,CAAA;QAEpB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;YAC1B,IAAI,GAAG,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;YAC/B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC;oBACvB,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAA;gBACpB,CAAC;gBACD,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;YACzB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAe,uBAAuB,CAAC,OAA4B;;QAEjE,MAAM,UAAU,GAAG,IAAA,gCAAmB,EAAC,IAAA,aAAG,GAAE,CAAC,CAAA;QAC7C,IAAI,MAAM,GAAG,EAAE,CAAA;QAEf,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,yBAAyB,EAAE,UAAU,CAAC,CAAA;YACnD,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,aAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;gBACnD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;gBACzB,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAA;YAC5C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,eAAe,IAAI,OAAO,EAAE,CAAC;YAC/B,IAAK,OAAO,CAAC,aAA0B,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1D,OAAO,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAA;gBACzD,OAAO,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAA;YACpF,CAAC;QACH,CAAC;QAED,OAAO,IAAA,cAAK,EAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,CAAC;CAAA;AAGD,SAAe,GAAG,CAAC,IAAc;;;QAC/B,mBAAO;aACJ,OAAO,CAAC,sBAAsB,CAAC;aAC/B,WAAW,CAAC,wDAAwD,CAAC;aACrE,MAAM,CAAC,sBAAsB,EAAE,gCAAgC,EAAE,GAAG,CAAC;aACrE,MAAM,CAAC,oBAAoB,EAAE,sBAAsB,EAAE,MAAA,OAAO,CAAC,GAAG,CAAC,cAAc,mCAAI,sBAAsB,CAAC;aAC1G,MAAM,CAAC,iBAAiB,EAAE,0BAA0B,CAAC;aACrD,MAAM,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,CAAC;aAC7C,MAAM,CAAC,CAAO,OAA4B,EAAE,EAAE;YAC7C,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;YAChD,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,gBAAM,CAAC,MAAM,CAAC,EAAE,kBAAkB,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,uBAAuB,CAAC,EAAE,CAAC,CAAA;YAC7G,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;YAClD,MAAM,eAAe,GAAG,OAAO;iBAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC;iBAChD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;YAEzB,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAL,oBAAK,EAAE,MAAM,EAAN,qBAAM,EAAE,CAAC,CAAA;YACtD,MAAM,SAAS,GAAG,GAA2B,EAAE;gBAC7C,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;oBAChB,OAAO,IAAI,CAAA;gBACb,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,wGAAwG,CAAC,CAAA;gBAC5I,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;oBACvB,OAAO,IAAI,CAAA;gBACb,CAAC;qBAAM,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;oBAC7B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;oBAC/C,OAAO,SAAS,EAAE,CAAA;gBACpB,CAAC;qBAAM,CAAC;oBACN,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC,CAAA,CAAA;YAED,MAAM,IAAI,GAAG,MAAM,SAAS,EAAE,CAAA;YAC9B,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;gBACpC,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,SAAS,+BAA+B,CAAA;gBAC/D,MAAM,IAAI,GAAG,IAAI,iBAAQ,EAAE,CAAA;gBAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAChD,MAAM,QAAQ,GAAG,eAAe,CAAC,CAAC,CAAC,CAAA;oBACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,IAAA,oBAAU,EAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAA;oBAC9D,OAAO,CAAC,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAA;gBAC9C,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,cAAc,CAAyE,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;gBACpI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,CAAC,CAAA;gBAC/F,EAAE,CAAC,KAAK,EAAE,CAAA;YACZ,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,KAAK,EAAE,CAAA;YACZ,CAAC;QACH,CAAC,CAAA,CAAC,CAAA;QAEJ,mBAAO;aACJ,OAAO,CAAC,kBAAkB,CAAC;aAC3B,WAAW,CAAC,4FAA4F,CAAC;aACzG,MAAM,CAAC,sBAAsB,EAAE,oDAAoD,CAAC;aACpF,MAAM,CAAC,oBAAoB,EAAE,sBAAsB,EAAE,MAAA,OAAO,CAAC,GAAG,CAAC,cAAc,mCAAI,sBAAsB,CAAC;aAC1G,MAAM,CAAC,qBAAqB,EAAE,0BAA0B,CAAC;aACzD,MAAM,CAAC,iBAAiB,EAAE,0BAA0B,CAAC;aACrD,MAAM,CAAC,mBAAmB,EAAE,oCAAoC,CAAC;aACjE,QAAQ,CAAC,qBAAqB,EAAE,iCAAiC,CAAC;aAClE,MAAM,CAAC,CAAO,aAAuB,EAAE,OAA4B,EAAE,OAAgB,EAAE,EAAE;YACxF,MAAM,UAAU,GAAG,IAAA,gCAAmB,EAAC,IAAA,aAAG,GAAE,CAAC,CAAA;YAC7C,IAAI,MAAM,GAAG,EAAE,CAAA;YAEf,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,yBAAyB,EAAE,UAAU,CAAC,CAAA;gBACnD,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,aAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;oBACnD,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;oBACzB,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAA;gBAC5C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM;gBACR,CAAC;YACH,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,uBAAuB,iCAAK,OAAO,KAAE,aAAa,EAAE,aAAa,IAAE,CAAA;YAC1F,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;YACjD,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;YAChD,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;YAChD,CAAC;YAED,MAAM,OAAO,GAAG,cAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;YACjD,MAAM,WAAW,GAAG,MAAM,aAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAEvD,IAAI,IAAI,GAAG,IAAI,CAAA;YACf,IAAI,CAAC;gBACH,IAAI,GAAG,IAAA,eAAQ,EAAC,WAAW,CAAC,CAAA;YAC9B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC;oBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;gBAChC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;oBAC3D,MAAM,GAAG,CAAA;gBACX,CAAC;YACH,CAAC;YAED,MAAM,IAAI,mBACR,OAAO,EAAE,QAAQ,CAAC,aAAa,EAC/B,YAAY,EAAE,IAAI,sBACT,CAAC,QAAQ,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAC/E,CAAA;YAED,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,SAAS,mBAAmB,CAAA;YACnD,MAAM,IAAI,GAAG,MAAM,cAAc,CAAyB,GAAG,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;YACrF,OAAO,CAAC,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAA;YAC5C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE;gBAC3C,MAAM,CAAC,GAAG,GAAG,QAAQ,CAAC,SAAS,IAAI,GAAG,OAAO,CAAA;gBAC7C,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAA;gBACjC,aAAE,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC,SAAS,IAAI,GAAG,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;YACjF,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA,CAAC,CAAA;QAEJ,mBAAO;aACJ,OAAO,CAAC,aAAa,CAAC;aACtB,WAAW,CAAC,2DAA2D,CAAC;aACxE,MAAM,CAAC,sBAAsB,EAAE,gCAAgC,EAAE,GAAG,CAAC;aACrE,MAAM,CAAC,OAAO,EAAE,qBAAqB,EAAE,KAAK,CAAC;aAC7C,MAAM,CAAC,CAAO,OAA4B,EAAE,EAAE;YAE7C,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;YACjD,CAAC;YACD,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAL,oBAAK,EAAE,MAAM,EAAN,qBAAM,EAAE,CAAC,CAAA;YACtD,MAAM,SAAS,GAAG,GAA2B,EAAE;gBAC7C,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;oBAChB,OAAO,IAAI,CAAA;gBACb,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,yGAAyG,CAAC,CAAA;gBAC7I,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;oBACvB,OAAO,IAAI,CAAA;gBACb,CAAC;qBAAM,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;oBAC7B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;oBAC/C,OAAO,SAAS,EAAE,CAAA;gBACpB,CAAC;qBAAM,CAAC;oBACN,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC,CAAA,CAAA;YACD,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAA;YAC7B,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,KAAK,GAAG,MAAM,IAAA,kBAAO,EAAC,OAAO,CAAC,UAAU,CAAC,CAAA;gBAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC9C,MAAM,EAAE,GAAG,IAAA,mBAAO,EAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;oBAChD,MAAM,IAAI,GAAG,MAAM,IAAA,mBAAQ,EAAC,EAAE,EAAE,OAAO,CAAC,CAAA;oBACxC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;oBAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;oBAC1D,MAAM,IAAA,oBAAS,EAAC,EAAE,EAAE,SAAS,CAAC,CAAA;gBAChC,CAAC;gBACD,EAAE,CAAC,KAAK,EAAE,CAAA;YACZ,CAAC;YACD,EAAE,CAAC,KAAK,EAAE,CAAA;QAEZ,CAAC,CAAA,CAAC,CAAA;QAGJ,MAAM,mBAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC;CAAA;AAED,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- export type LocaleRegion = 'en' | 'en-US' | 'en-US-genz' | 'fr-FR' | 'de-DE' | 'nl-NL' | 'jp-JP' | string;
2
+ export type LocaleRegion = string;
3
3
  export interface TranslationLeaf {
4
4
  value: string;
5
5
  context?: string;
@@ -16,18 +16,28 @@ export interface ContextType {
16
16
  t: (key: string, options?: {
17
17
  locale?: LocaleRegion;
18
18
  }) => string;
19
+ ssr: boolean;
19
20
  }
20
21
  export declare const GlotstackContext: React.Context<ContextType>;
21
22
  interface GlotstackProviderProps {
22
23
  children: React.ReactNode;
23
- initialTranslations?: Translations;
24
+ initialTranslations?: Record<string, Translations>;
24
25
  initialLocale?: LocaleRegion;
25
26
  onTranslationLoaded?: (locale: LocaleRegion, translations: Translations) => void;
26
27
  onLocaleChange?: (locale: LocaleRegion) => void;
27
- importMethod: (locale: LocaleRegion) => Promise<Translations>;
28
+ importMethod: ContextType['importMethod'];
29
+ ssr?: boolean;
30
+ }
31
+ export declare enum LogLevel {
32
+ DEBUG = 0,
33
+ LOG = 1,
34
+ INFO = 2,
35
+ WARNING = 3,
36
+ ERROR = 4
28
37
  }
38
+ export declare const setLogLevel: (level: LogLevel) => void;
29
39
  export declare const access: (key: string, locale: LocaleRegion, translations: Translations) => string;
30
- export declare const GlotstackProvider: ({ children, initialLocale, initialTranslations, onLocaleChange, onTranslationLoaded, importMethod }: GlotstackProviderProps) => React.JSX.Element;
40
+ export declare const GlotstackProvider: ({ children, initialLocale, initialTranslations, onLocaleChange, onTranslationLoaded, importMethod, ssr }: GlotstackProviderProps) => import("react/jsx-runtime").JSX.Element;
31
41
  export declare const useGlotstack: () => ContextType;
32
42
  export declare const useTranslations: (_options?: Record<never, never>) => ContextType;
33
43
  export {};
package/dist/index.js CHANGED
@@ -32,8 +32,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
32
32
  });
33
33
  };
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.useTranslations = exports.useGlotstack = exports.GlotstackProvider = exports.access = exports.GlotstackContext = void 0;
35
+ exports.useTranslations = exports.useGlotstack = exports.GlotstackProvider = exports.access = exports.setLogLevel = exports.LogLevel = exports.GlotstackContext = void 0;
36
+ const jsx_runtime_1 = require("react/jsx-runtime");
36
37
  const React = __importStar(require("react"));
38
+ const object_1 = require("./util/object");
37
39
  exports.GlotstackContext = React.createContext({
38
40
  translations: {},
39
41
  loadTranslations: () => { throw new Error('no import method set'); },
@@ -41,9 +43,46 @@ exports.GlotstackContext = React.createContext({
41
43
  locale: null,
42
44
  importMethod: (_locale) => { throw new Error('import method not set'); },
43
45
  t: () => { throw new Error('import method not set'); },
46
+ ssr: false
44
47
  });
48
+ var LogLevel;
49
+ (function (LogLevel) {
50
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
51
+ LogLevel[LogLevel["LOG"] = 1] = "LOG";
52
+ LogLevel[LogLevel["INFO"] = 2] = "INFO";
53
+ LogLevel[LogLevel["WARNING"] = 3] = "WARNING";
54
+ LogLevel[LogLevel["ERROR"] = 4] = "ERROR";
55
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
56
+ const LogLevelToFunc = {
57
+ [LogLevel.DEBUG]: console.debug,
58
+ [LogLevel.INFO]: console.info,
59
+ [LogLevel.LOG]: console.log,
60
+ [LogLevel.WARNING]: console.warn,
61
+ [LogLevel.ERROR]: console.error,
62
+ };
63
+ let logLevel = LogLevel.DEBUG;
64
+ const setLogLevel = (level) => {
65
+ logLevel = level;
66
+ };
67
+ exports.setLogLevel = setLogLevel;
68
+ const makeLoggingFunction = (level) => (...args) => {
69
+ const func = LogLevelToFunc[level];
70
+ if (level < logLevel) {
71
+ return;
72
+ }
73
+ return func(`[level=${level} logLevel=${logLevel}][glotstack.ai]`, ...args);
74
+ };
75
+ const logger = {
76
+ debug: makeLoggingFunction(LogLevel.DEBUG),
77
+ info: makeLoggingFunction(LogLevel.INFO),
78
+ warn: makeLoggingFunction(LogLevel.WARNING),
79
+ error: makeLoggingFunction(LogLevel.ERROR),
80
+ };
45
81
  const access = (key, locale, translations) => {
46
82
  var _a;
83
+ if (translations == null) {
84
+ return key;
85
+ }
47
86
  const access = [...key.split('.')];
48
87
  const localeTranslations = translations === null || translations === void 0 ? void 0 : translations[locale];
49
88
  if (localeTranslations == null) {
@@ -56,61 +95,71 @@ const access = (key, locale, translations) => {
56
95
  return ((_a = value === null || value === void 0 ? void 0 : value.value) !== null && _a !== void 0 ? _a : key);
57
96
  };
58
97
  exports.access = access;
59
- const GlotstackProvider = ({ children, initialLocale, initialTranslations, onLocaleChange, onTranslationLoaded, importMethod }) => {
98
+ const GlotstackProvider = ({ children, initialLocale, initialTranslations, onLocaleChange, onTranslationLoaded, importMethod, ssr }) => {
60
99
  if (initialLocale == null) {
61
100
  throw new Error('initialLocale must be set');
62
101
  }
63
102
  const [locale, setLocale] = React.useState(initialLocale);
64
- const [translations, setTranslations] = React.useState(initialTranslations);
103
+ const translationsRef = React.useRef(initialTranslations || null);
65
104
  const loadingRef = React.useRef({});
66
- const loadTranslations = React.useCallback((locale) => __awaiter(void 0, void 0, void 0, function* () {
67
- var _a, _b;
105
+ const loadTranslations = React.useCallback((locale, opts) => __awaiter(void 0, void 0, void 0, function* () {
106
+ var _a, _b, _c, _d, _e, _f;
107
+ // TODO: if translations are loaded only reload if some condition is
68
108
  try {
69
- if (((_a = loadingRef.current) === null || _a === void 0 ? void 0 : _a[locale]) != null) {
109
+ if (((_a = loadingRef.current) === null || _a === void 0 ? void 0 : _a[locale]) != null && (opts === null || opts === void 0 ? void 0 : opts.force) != true) {
110
+ logger.debug('Waiting for translations already loading', locale);
70
111
  return (yield ((_b = loadingRef.current) === null || _b === void 0 ? void 0 : _b[locale]));
71
112
  }
72
- loadingRef.current[locale] = importMethod(locale);
113
+ if (((_c = translationsRef.current) === null || _c === void 0 ? void 0 : _c[locale]) != null && (opts === null || opts === void 0 ? void 0 : opts.force) != true) {
114
+ logger.debug('Skipping load for translations', locale, (_d = translationsRef.current) === null || _d === void 0 ? void 0 : _d[locale], translationsRef.current);
115
+ return (_e = translationsRef.current) === null || _e === void 0 ? void 0 : _e[locale];
116
+ }
117
+ if (loadingRef.current != null) {
118
+ logger.debug('Loading translations', locale, (0, object_1.merge)({}, (_f = translationsRef.current) !== null && _f !== void 0 ? _f : {}));
119
+ loadingRef.current[locale] = importMethod(locale);
120
+ }
73
121
  const result = yield loadingRef.current[locale];
74
122
  if (result == null) {
75
123
  throw new Error(`Failed to load translation ${locale} ${JSON.stringify(result)}`);
76
124
  }
77
- setTranslations(Object.assign(Object.assign({}, translations), { [locale]: result }));
125
+ if (translationsRef.current) {
126
+ translationsRef.current[locale] = result;
127
+ }
78
128
  onTranslationLoaded === null || onTranslationLoaded === void 0 ? void 0 : onTranslationLoaded(locale, result);
79
129
  return result;
80
130
  }
81
131
  catch (err) {
82
- console.error('Unable to import translations', err);
132
+ logger.error('Unable to import translations', err);
83
133
  throw err;
84
134
  }
85
- }), [importMethod, translations, onTranslationLoaded, setTranslations]);
135
+ }), [importMethod, onTranslationLoaded]);
86
136
  React.useEffect(() => {
87
137
  const run = () => __awaiter(void 0, void 0, void 0, function* () {
88
138
  onLocaleChange === null || onLocaleChange === void 0 ? void 0 : onLocaleChange(locale);
89
- const result = yield loadTranslations(locale);
139
+ yield loadTranslations(locale);
90
140
  });
91
141
  React.startTransition(() => {
92
142
  run();
93
143
  });
94
144
  }, [locale]);
95
145
  const context = React.useMemo(() => {
146
+ var _a;
96
147
  return {
97
148
  setLocale,
98
- translations: translations !== null && translations !== void 0 ? translations : {},
149
+ translations: (_a = translationsRef.current) !== null && _a !== void 0 ? _a : {},
99
150
  locale,
100
151
  importMethod,
101
152
  loadTranslations,
102
153
  t: (key, opts) => {
103
- React.useEffect(() => {
104
- if ((opts === null || opts === void 0 ? void 0 : opts.locale) == null) {
105
- return;
106
- }
107
- loadTranslations(opts === null || opts === void 0 ? void 0 : opts.locale);
108
- }, [locale]);
109
- return (0, exports.access)(key, locale, translations !== null && translations !== void 0 ? translations : {});
110
- }
154
+ var _a, _b, _c;
155
+ const resolvedLocale = (_a = opts === null || opts === void 0 ? void 0 : opts.locale) !== null && _a !== void 0 ? _a : locale;
156
+ loadTranslations(resolvedLocale);
157
+ return (0, exports.access)(key, (_b = opts === null || opts === void 0 ? void 0 : opts.locale) !== null && _b !== void 0 ? _b : locale, (_c = translationsRef.current) !== null && _c !== void 0 ? _c : {});
158
+ },
159
+ ssr: ssr == true,
111
160
  };
112
- }, [locale, importMethod, translations]);
113
- return React.createElement(exports.GlotstackContext.Provider, { value: context }, children);
161
+ }, [locale, importMethod]);
162
+ return (0, jsx_runtime_1.jsx)(exports.GlotstackContext.Provider, { value: context, children: children });
114
163
  };
115
164
  exports.GlotstackProvider = GlotstackProvider;
116
165
  const useGlotstack = () => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import globals from "globals";
2
+ import tseslint from "typescript-eslint";
3
+ import { defineConfig, globalIgnores } from "eslint/config";
4
+ import i18next from 'eslint-plugin-i18next';
5
+
6
+
7
+ export default defineConfig([
8
+ { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"], languageOptions: { globals: globals.browser } },
9
+ globalIgnores([
10
+ 'node_modules/*', // ignore node modules
11
+ '**/*.d.ts', // ignore type definitions
12
+ ]),
13
+ tseslint.configs.base,
14
+ i18next.configs['flat/recommended'],
15
+ ]);
package/package.json CHANGED
@@ -1,34 +1,41 @@
1
1
  {
2
2
  "name": "glotstack",
3
- "version": "0.0.4",
3
+ "version": "0.0.7",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "author": "JD Cumpson",
7
7
  "license": "MIT",
8
8
  "private": false,
9
9
  "dependencies": {
10
- "commander": "^13.1.0"
10
+ "@eslint/js": "^9.26.0",
11
+ "commander": "^13.1.0",
12
+ "eslint": "^9.26.0",
13
+ "eslint-plugin-i18next": "^6.1.1",
14
+ "eslint-plugin-react": "^7.37.5",
15
+ "form-data": "^4.0.2",
16
+ "undici": "^7.9.0"
11
17
  },
12
18
  "devDependencies": {
13
19
  "@types/js-yaml": "^4.0.9",
14
20
  "@types/node": "^22.15.17",
15
- "@types/react": "^19.1.3",
21
+ "@types/react": "^18.3.1",
22
+ "@types/react-dom": "^18.3.1",
23
+ "globals": "^16.1.0",
16
24
  "js-yaml": "^4.1.0",
25
+ "nodemon": "^3.1.10",
17
26
  "typescript": "5.4.4",
18
- "typescript-eslint": "^8.17.0"
27
+ "typescript-eslint": "^8.32.1"
19
28
  },
20
29
  "peerDependencies": {
21
- "@types/react": "^19.1.3",
22
- "react": "^18.3.1"
23
- },
24
- "resolutions": {
25
- "react": "18.3.1"
30
+ "react": "^18.3.1",
31
+ "react-dom": "^18.3.1"
26
32
  },
27
33
  "bin": {
28
34
  "glotstack": "dist/cli.js"
29
35
  },
30
36
  "scripts": {
31
37
  "build": "tsc && scripts/fix-shebang.sh dist/cli.js",
38
+ "watch": "nodemon --watch src --ext ts,tsx,mjs,json --exec \"bash -c 'npm run build'\"",
32
39
  "prepublishOnly": "yarn run build",
33
40
  "glotstack": "node dist/cli.js"
34
41
  }
package/src/cli.tsx CHANGED
@@ -1,17 +1,155 @@
1
1
  import { Command, program } from 'commander'
2
2
  import path from 'path'
3
- import { promises as fs } from 'fs'
3
+ import { promises as fs, createReadStream } from 'fs'
4
4
  import { findGlotstackConfig } from './util/findConfig'
5
5
  import { cwd } from 'process'
6
6
  import { merge } from './util/object'
7
7
  import { loadYaml } from './util/yaml'
8
+ import eslint from 'eslint'
9
+ import * as readline from "node:readline/promises"
10
+ import { stdin as input, stdout as output } from "node:process"
11
+ import { Translations } from 'src'
12
+ import { fetch } from 'undici'
13
+ import { FormData } from 'undici'
14
+ import { openAsBlob } from 'node:fs'
15
+ import { readdir, readFile, writeFile } from 'node:fs/promises'
16
+ import { resolve } from 'node:path'
17
+
18
+ const fetchGlotstack = async function <T>(url: string, apiKey: string, body: Record<string, any> | FormData, overrideHeaders?: Record<string, any>): Promise<T> {
19
+ console.info(`Extracting translations with: ${url}`)
20
+
21
+ const headers: Record<string, any> = {
22
+ 'authorization': `Bearer ${apiKey}`,
23
+ ...(overrideHeaders == null ? {} : overrideHeaders),
24
+ }
25
+
26
+ let payloadBody: FormData | string
27
+
28
+ if (!(body instanceof FormData)) {
29
+ headers['content-type'] = 'application/json'
30
+ payloadBody = JSON.stringify(body)
31
+ } else {
32
+ payloadBody = body
33
+ }
34
+
35
+ try {
36
+ const res = await fetch(url, { method: 'POST', body: payloadBody, headers })
37
+ if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`)
38
+ return res.json() as T
39
+ } catch (err) {
40
+ console.error('Fetch failed:', err)
41
+ process.exit(1)
42
+ }
43
+ }
44
+
45
+ function unflatten(flat: Record<string, any>): Record<string, any> {
46
+ const result: Record<string, any> = {}
47
+
48
+ for (const flatKey in flat) {
49
+ const parts = flatKey.split('.')
50
+ let current = result
51
+
52
+ parts.forEach((part, idx) => {
53
+ if (idx === parts.length - 1) {
54
+ current[part] = flat[flatKey]
55
+ } else {
56
+ if (!(part in current)) {
57
+ current[part] = {}
58
+ }
59
+ current = current[part]
60
+ }
61
+ })
62
+ }
63
+
64
+ return result
65
+ }
66
+
67
+ async function resolveConfigAndOptions(options: Record<string, any>) {
68
+
69
+ const configPath = findGlotstackConfig(cwd())
70
+ let config = {}
71
+
72
+ if (configPath != null) {
73
+ console.info('Loading config file at ', configPath)
74
+ try {
75
+ const text = await fs.readFile(configPath, 'utf-8')
76
+ config = JSON.parse(text)
77
+ console.info('Loaded config file', config)
78
+ } catch (err) {
79
+ //pass
80
+ }
81
+ }
82
+
83
+ if ('outputLocales' in options) {
84
+ if ((options.outputLocales as string[]).includes('en-US')) {
85
+ console.warn('en-US detected in outputLocales, removing')
86
+ options.outputLocales = options.outputLocales.filter((x: string) => x !== 'en-US')
87
+ }
88
+ }
89
+
90
+ return merge(config, options)
91
+ }
8
92
 
9
93
 
10
94
  async function run(args: string[]) {
95
+ program
96
+ .command('extract-translations')
97
+ .description('extract translations from all compatible source files.')
98
+ .option('--source-path [path]', 'to source files root directory', '.')
99
+ .option('--api-origin [url]', 'glotstack api origin', process.env.GLOTSTACK_HOST ?? 'https://glotstack.ai')
100
+ .option('--api-key [key]', 'api key for glotstack.ai')
101
+ .option('--yes', 'skip confirm checks', false)
102
+ .action(async (options: Record<string, any>) => {
103
+ if (!options.apiOrigin) {
104
+ throw new Error('apiOrigin must be specified')
105
+ }
106
+
107
+ const linter = new eslint.ESLint({ overrideConfigFile: path.join(__dirname, '..', 'eslint-raw-string.mjs') })
108
+ const results = await linter.lintFiles(["./**/*"])
109
+ const filesWithIssues = results
110
+ .filter((r) => r.errorCount + r.warningCount > 0)
111
+ .map((r) => r.filePath)
112
+
113
+ const rl = readline.createInterface({ input, output })
114
+ const askToSend = async (): Promise<boolean> => {
115
+ if (options.yes) {
116
+ return true
117
+ }
118
+ const response = await rl.question(`Your source are going to be sent to our LLM -- they should not contain any secrets. Proceed? (yes/no):`)
119
+ if (response === 'yes') {
120
+ return true
121
+ } else if (response !== 'no') {
122
+ console.error('Please respond with yes or no.')
123
+ return askToSend()
124
+ } else {
125
+ return false
126
+ }
127
+ }
128
+
129
+ const send = await askToSend()
130
+ if (send) {
131
+ console.info('Sending files to LLM')
132
+ const url = `${options.apiOrigin}/uploads/translations/extract`
133
+ const form = new FormData()
134
+
135
+ for (let i = 0; i < filesWithIssues.length; i++) {
136
+ const filePath = filesWithIssues[i]
137
+ form.append(`file_${i}`, await openAsBlob(filePath), filePath)
138
+ console.debug(`Uploading file: ${filePath}`)
139
+ }
140
+ const data = await fetchGlotstack<{ translations: { name: string; modified_source: { url: string } }[] }>(url, options.apiKey, form)
141
+ data.translations.map(elem => console.info(`${elem.name}:\n ${elem.modified_source.url}\n\n`))
142
+ rl.close()
143
+ } else {
144
+ rl.close()
145
+ }
146
+ })
147
+
11
148
  program
12
149
  .command('get-translations')
150
+ .description('fetch translations for all [output-locals...]. Use .glotstack.json for repeatable results.')
13
151
  .option('--source-path [path]', 'path to en-US.json (or your canonical source json)')
14
- .option('--api-origin [url]', 'glotstack api origin', 'http://localhost:4001')
152
+ .option('--api-origin [url]', 'glotstack api origin', process.env.GLOTSTACK_HOST ?? 'https://glotstack.ai')
15
153
  .option('--output-dir [path]', 'path to output directory')
16
154
  .option('--api-key [key]', 'api key for glotstack.ai')
17
155
  .option('--project-id [id]', '(optional) specific project to use')
@@ -26,77 +164,95 @@ async function run(args: string[]) {
26
164
  const text = await fs.readFile(configPath, 'utf-8')
27
165
  config = JSON.parse(text)
28
166
  console.info('Loaded config file', config)
29
- } catch(err) {
167
+ } catch (err) {
30
168
  //pass
31
169
  }
32
170
  }
33
171
 
34
- const resolved = merge(config, options, { outputLocales })
35
- const { apiOrigin, sourcePath, outputDir, projectId} = resolved
36
-
37
- if ((resolved.outputLocales as string[]).includes('en-US')) {
38
- console.warn('en-US detected in outputLocales, removing');
39
- resolved.outputLocales = resolved.outputLocales.filter((x: string) => x !== 'en-US')
40
- }
41
-
42
- if (!sourcePath) {
172
+ const resolved = await resolveConfigAndOptions({...options, outputLocales: outputLocales})
173
+ if (!resolved.sourcePath) {
43
174
  throw new Error('sourcePath must be specified')
44
175
  }
45
- if (!apiOrigin) {
176
+ if (!resolved.apiOrigin) {
46
177
  throw new Error('apiOrigin must be specified')
47
178
  }
48
- if (!outputDir) {
179
+ if (!resolved.outputDir) {
49
180
  throw new Error('outputDir must be specified')
50
181
  }
51
182
 
52
- const url = `${apiOrigin}/api/translations`
53
- console.info(`Fetching translations from: ${url}`)
54
-
55
- const absPath = path.resolve(sourcePath)
183
+ const absPath = path.resolve(resolved.sourcePath)
56
184
  const fileContent = await fs.readFile(absPath, 'utf-8')
57
185
 
58
186
  let json = null
59
187
  try {
60
188
  json = loadYaml(fileContent)
61
- } catch(err) {
189
+ } catch (err) {
62
190
  try {
63
191
  json = JSON.parse(fileContent)
64
- } catch(err) {
192
+ } catch (err) {
65
193
  console.error('Unable to parse source file ', absPath, err)
66
- throw err;
194
+ throw err
67
195
  }
68
196
  }
69
197
 
70
198
  const body = {
71
199
  locales: resolved.outputLocales,
72
200
  translations: json,
73
- ...{ ... (projectId != null ? {projectId} : {})},
201
+ ...{ ... (resolved.projectId != null ? { projectId: resolved.projectId } : {}) },
74
202
  }
75
203
 
76
- const headers ={
77
- 'Content-Type': 'application/json',
78
- 'Authorization': `Bearer ${resolved.apiKey}` ,
79
- }
204
+ const url = `${options.apiOrigin}/api/translations`
205
+ const data = await fetchGlotstack<{ data: Translations }>(url, resolved.apiKey, body)
206
+ console.info('Received translations:', data)
207
+ Object.entries(data.data).map(([key, val]) => {
208
+ const p = `${resolved.outputDir}/${key}.json`
209
+ console.info(`Writing file ${p}`)
210
+ fs.writeFile(`${resolved.outputDir}/${key}.json`, JSON.stringify(val, null, 2))
211
+ })
212
+ })
80
213
 
81
- try {
82
- const res = await fetch(url, { method: 'POST', body: JSON.stringify(body), headers })
83
- if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`)
84
-
85
- const data = await res.json()
86
- console.info('Received translations:', data)
87
- Object.entries(data.data).map(([key, val]) => {
88
- const p = `${outputDir}/${key}.json`
89
- console.info(`Writing file ${p}`)
90
- fs.writeFile(`${outputDir}/${key}.json`, JSON.stringify(val, null, 2))
91
- })
92
- // fs.writeFile(`${outputDir}/source.json`, JSON.stringify(json, null, 2))
93
- } catch (err) {
94
- console.error('Fetch failed:', err)
95
- process.exit(1)
214
+ program
215
+ .command('format-json')
216
+ .description('format files in --source-path [path] to nested (not flat)')
217
+ .option('--source-path [path]', 'to source files root directory', '.')
218
+ .option('--yes', 'skip confirm checks', false)
219
+ .action(async (options: Record<string, any>) => {
220
+
221
+ if (!options.sourcePath) {
222
+ throw new Error('sourcePath must be specified')
96
223
  }
224
+ const rl = readline.createInterface({ input, output })
225
+ const askToSend = async (): Promise<boolean> => {
226
+ if (options.yes) {
227
+ return true
228
+ }
229
+ const response = await rl.question(`This will update your source files -- have you checked them into SCM/git? Type yes to proceed (yes/no):`)
230
+ if (response === 'yes') {
231
+ return true
232
+ } else if (response !== 'no') {
233
+ console.error('Please respond with yes or no.')
234
+ return askToSend()
235
+ } else {
236
+ return false
237
+ }
238
+ }
239
+ const yes = await askToSend()
240
+ if (yes) {
241
+ const files = await readdir(options.sourcePath)
242
+ for (let i = 0; i < (await files).length; i++) {
243
+ const fp = resolve(options.sourcePath, files[i])
244
+ const text = await readFile(fp, 'utf-8')
245
+ const json = JSON.parse(text)
246
+ const formatted = JSON.stringify(unflatten(json), null, 2)
247
+ await writeFile(fp, formatted)
248
+ }
249
+ rl.close()
250
+ }
251
+ rl.close()
97
252
 
98
253
  })
99
254
 
255
+
100
256
  await program.parseAsync(args)
101
257
  }
102
258
 
package/src/index.tsx CHANGED
@@ -1,15 +1,8 @@
1
1
  import * as React from 'react'
2
- import { merge, isEqual } from './util/object'
2
+ import { merge } from './util/object'
3
+ import { debug } from 'node:console'
3
4
 
4
- export type LocaleRegion =
5
- | 'en'
6
- | 'en-US'
7
- | 'en-US-genz'
8
- | 'fr-FR'
9
- | 'de-DE'
10
- | 'nl-NL'
11
- | 'jp-JP'
12
- | string
5
+ export type LocaleRegion = string
13
6
 
14
7
 
15
8
  export interface TranslationLeaf {
@@ -21,13 +14,15 @@ export interface Translations {
21
14
  [key: string]: Translations | TranslationLeaf
22
15
  }
23
16
 
17
+
24
18
  export interface ContextType {
25
19
  translations: Translations
26
20
  locale: string | null
27
21
  loadTranslations: (locale: LocaleRegion) => Promise<Translations>
28
22
  setLocale: (locale: LocaleRegion) => void
29
- importMethod: (locale: LocaleRegion) => Promise<Translations>
23
+ importMethod: (locale: LocaleRegion) => Promise<Translations>
30
24
  t: (key: string, options?: { locale?: LocaleRegion }) => string
25
+ ssr: boolean
31
26
  }
32
27
 
33
28
  export const GlotstackContext = React.createContext<ContextType>({
@@ -37,18 +32,61 @@ export const GlotstackContext = React.createContext<ContextType>({
37
32
  locale: null,
38
33
  importMethod: (_locale: LocaleRegion) => { throw new Error('import method not set') },
39
34
  t: () => { throw new Error('import method not set') },
35
+ ssr: false
40
36
  })
41
37
 
42
38
  interface GlotstackProviderProps {
43
39
  children: React.ReactNode
44
- initialTranslations?: Translations
40
+ initialTranslations?: Record<string, Translations>
45
41
  initialLocale?: LocaleRegion
46
42
  onTranslationLoaded?: (locale: LocaleRegion, translations: Translations) => void
47
43
  onLocaleChange?: (locale: LocaleRegion) => void
48
- importMethod: (locale: LocaleRegion) => Promise<Translations>
44
+ importMethod: ContextType['importMethod']
45
+ ssr?: boolean
46
+ }
47
+
48
+ export enum LogLevel {
49
+ DEBUG = 0,
50
+ LOG = 1,
51
+ INFO = 2,
52
+ WARNING = 3,
53
+ ERROR = 4,
54
+ }
55
+
56
+ const LogLevelToFunc: Record<LogLevel, (...args: Parameters<typeof console.info>) => void> = {
57
+ [LogLevel.DEBUG]: console.debug,
58
+ [LogLevel.INFO]: console.info,
59
+ [LogLevel.LOG]: console.log,
60
+ [LogLevel.WARNING]: console.warn,
61
+ [LogLevel.ERROR]: console.error,
62
+ } as const
63
+
64
+ let logLevel: LogLevel = LogLevel.DEBUG
65
+
66
+ export const setLogLevel = (level: LogLevel) => {
67
+ logLevel = level
68
+ }
69
+
70
+ const makeLoggingFunction = (level: LogLevel) => (...args: Parameters<typeof console.info>) => {
71
+ const func = LogLevelToFunc[level]
72
+ if (level < logLevel) {
73
+ return
74
+ }
75
+ return func(`[level=${level} logLevel=${logLevel}][glotstack.ai]`, ...args)
76
+ }
77
+
78
+ const logger = {
79
+ debug: makeLoggingFunction(LogLevel.DEBUG),
80
+ info: makeLoggingFunction(LogLevel.INFO),
81
+ warn: makeLoggingFunction(LogLevel.WARNING),
82
+ error: makeLoggingFunction(LogLevel.ERROR),
83
+
49
84
  }
50
85
 
51
86
  export const access = (key: string, locale: LocaleRegion, translations: Translations) => {
87
+ if (translations == null) {
88
+ return key
89
+ }
52
90
  const access = [...key.split('.')] as [LocaleRegion, ...string[]]
53
91
  const localeTranslations = translations?.[locale]
54
92
 
@@ -64,39 +102,49 @@ export const access = (key: string, locale: LocaleRegion, translations: Translat
64
102
  return (value?.value ?? key) as string
65
103
  }
66
104
 
67
- export const GlotstackProvider = ({ children, initialLocale, initialTranslations, onLocaleChange, onTranslationLoaded, importMethod }: GlotstackProviderProps) => {
105
+ export const GlotstackProvider = ({ children, initialLocale, initialTranslations, onLocaleChange, onTranslationLoaded, importMethod, ssr}: GlotstackProviderProps) => {
68
106
  if (initialLocale == null) {
69
107
  throw new Error('initialLocale must be set')
70
108
  }
71
-
72
109
  const [locale, setLocale] = React.useState<LocaleRegion>(initialLocale)
73
- const [translations, setTranslations] = React.useState(initialTranslations)
110
+ const translationsRef = React.useRef<Record<string, Translations>|null>(initialTranslations || null)
74
111
  const loadingRef = React.useRef<Record<string, Promise<Translations>>>({})
75
112
 
76
- const loadTranslations = React.useCallback(async (locale: string) => {
113
+ const loadTranslations = React.useCallback(async (locale: string, opts?: {force?: boolean}) => {
114
+ // TODO: if translations are loaded only reload if some condition is
77
115
  try {
78
- if (loadingRef.current?.[locale] != null) {
116
+ if (loadingRef.current?.[locale] != null && opts?.force != true) {
117
+ logger.debug('Waiting for translations already loading', locale)
79
118
  return (await loadingRef.current?.[locale])
80
119
  }
81
- loadingRef.current[locale] = importMethod(locale)
120
+ if (translationsRef.current?.[locale] != null && opts?.force != true) {
121
+ logger.debug('Skipping load for translations', locale, translationsRef.current?.[locale], translationsRef.current)
122
+ return translationsRef.current?.[locale]
123
+ }
124
+ if (loadingRef.current != null) {
125
+ logger.debug('Loading translations', locale, merge({}, translationsRef.current ?? {}))
126
+ loadingRef.current[locale] = importMethod(locale)
127
+ }
82
128
  const result = await loadingRef.current[locale]
83
129
 
84
130
  if (result == null) {
85
131
  throw new Error(`Failed to load translation ${locale} ${JSON.stringify(result)}`)
86
132
  }
87
- setTranslations({ ...translations, [locale]: result })
133
+ if (translationsRef.current) {
134
+ translationsRef.current[locale] = result
135
+ }
88
136
  onTranslationLoaded?.(locale, result)
89
137
  return result
90
138
  } catch (err) {
91
- console.error('Unable to import translations', err)
139
+ logger.error('Unable to import translations', err)
92
140
  throw err
93
141
  }
94
- }, [importMethod, translations, onTranslationLoaded, setTranslations])
142
+ }, [importMethod, onTranslationLoaded])
95
143
 
96
144
  React.useEffect(() => {
97
145
  const run = async () => {
98
146
  onLocaleChange?.(locale)
99
- const result = await loadTranslations(locale)
147
+ await loadTranslations(locale)
100
148
  }
101
149
  React.startTransition(() => {
102
150
  run()
@@ -106,22 +154,18 @@ export const GlotstackProvider = ({ children, initialLocale, initialTranslations
106
154
  const context = React.useMemo(() => {
107
155
  return {
108
156
  setLocale,
109
- translations: translations ?? {},
157
+ translations: translationsRef.current ?? {},
110
158
  locale,
111
159
  importMethod,
112
160
  loadTranslations,
113
161
  t: (key: string, opts?: { locale?: LocaleRegion }) => {
114
- React.useEffect(() => {
115
- if (opts?.locale == null) {
116
- return
117
- }
118
- loadTranslations(opts?.locale)
119
- }, [locale])
120
- return access(key, locale, translations ?? {})
121
- }
122
-
162
+ const resolvedLocale = opts?.locale ?? locale
163
+ loadTranslations(resolvedLocale)
164
+ return access(key, opts?.locale ?? locale, translationsRef.current ?? {})
165
+ },
166
+ ssr: ssr == true,
123
167
  }
124
- }, [locale, importMethod, translations])
168
+ }, [locale, importMethod])
125
169
 
126
170
  return <GlotstackContext.Provider value={context}>
127
171
  {children}
@@ -132,7 +176,6 @@ export const useGlotstack = () => {
132
176
  return React.useContext(GlotstackContext)
133
177
  }
134
178
 
135
-
136
179
  export const useTranslations = (_options?: Record<never, never>) => {
137
180
  const context = React.useContext(GlotstackContext)
138
181
  return context
package/tsconfig.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "module": "CommonJS",
9
9
  "declaration": true,
10
10
  "strict": true,
11
- "jsx": "react",
11
+ "jsx": "react-jsx",
12
12
  "sourceMap": true,
13
13
  "baseUrl": ".",
14
14
  "paths": {