glotfile 0.1.1 → 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/README.md +4 -4
- package/dist/server/cli.js +45 -11
- package/dist/server/server.js +37 -11
- package/dist/ui/assets/{index-DK-AGskd.js → index-DB5e5FME.js} +22 -8
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ to make.
|
|
|
8
8
|
|
|
9
9
|
- **One source of truth** — every string and translation lives in `glotfile.json`, committed alongside your code. Versioning, review, and rollback come from git. For large catalogs, run `glotfile split` to store the catalog as a `glotfile/` directory with one file per locale — so a one-locale change is a one-file `git diff` instead of a multi-megabyte one. The in-app experience is identical.
|
|
10
10
|
- **Local web UI** — run one command, edit in the browser, changes save straight back to the file.
|
|
11
|
-
- **AI translation** — fill in missing languages with Anthropic, OpenAI,
|
|
11
|
+
- **AI translation** — fill in missing languages with Anthropic, OpenAI, AWS Bedrock, or OpenRouter, using per-key context, a glossary, and screenshots.
|
|
12
12
|
- **Export anywhere** — generate Flutter ARB, Laravel PHP, i18next JSON, gettext `.po`, and Apple `.stringsdict` from the same source.
|
|
13
13
|
|
|
14
14
|
---
|
|
@@ -181,9 +181,9 @@ in the project directory. For example:
|
|
|
181
181
|
ANTHROPIC_API_KEY=sk-ant-...
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
(Amazon Nova, Claude, and Meta Llama). For the full setup of
|
|
186
|
-
env vars, model ids, regions, and the optional SDKs to install — see
|
|
184
|
+
Four providers are supported — Anthropic (default), OpenAI, AWS Bedrock
|
|
185
|
+
(Amazon Nova, Claude, and Meta Llama), and OpenRouter. For the full setup of
|
|
186
|
+
each — required env vars, model ids, regions, and the optional SDKs to install — see
|
|
187
187
|
**[docs/ai-providers.md](docs/ai-providers.md)**.
|
|
188
188
|
|
|
189
189
|
What the translator does for you:
|
package/dist/server/cli.js
CHANGED
|
@@ -277,7 +277,7 @@ var init_schema = __esm({
|
|
|
277
277
|
PLURAL_CATEGORIES = ["zero", "one", "two", "few", "many", "other"];
|
|
278
278
|
EXACT_SELECTOR_RE = /^=\d+$/;
|
|
279
279
|
LOCALE_CASES = ["lower-hyphen", "lower-underscore", "bcp47-hyphen", "bcp47-underscore"];
|
|
280
|
-
PROVIDERS = ["anthropic", "openai", "bedrock"];
|
|
280
|
+
PROVIDERS = ["anthropic", "openai", "bedrock", "openrouter"];
|
|
281
281
|
GlotfileError = class extends Error {
|
|
282
282
|
};
|
|
283
283
|
}
|
|
@@ -1768,6 +1768,17 @@ var init_anthropic = __esm({
|
|
|
1768
1768
|
|
|
1769
1769
|
// src/server/ai/openai.ts
|
|
1770
1770
|
import { createRequire } from "module";
|
|
1771
|
+
function loadOpenAIClient(opts) {
|
|
1772
|
+
const require2 = createRequire(import.meta.url);
|
|
1773
|
+
let OpenAICtor;
|
|
1774
|
+
try {
|
|
1775
|
+
const mod = require2("openai");
|
|
1776
|
+
OpenAICtor = mod.OpenAI ?? mod.default ?? mod;
|
|
1777
|
+
} catch {
|
|
1778
|
+
throw new Error("The OpenAI SDK is required for this provider. Install it: npm i openai");
|
|
1779
|
+
}
|
|
1780
|
+
return new OpenAICtor(opts);
|
|
1781
|
+
}
|
|
1771
1782
|
var OpenAIProvider;
|
|
1772
1783
|
var init_openai = __esm({
|
|
1773
1784
|
"src/server/ai/openai.ts"() {
|
|
@@ -1784,15 +1795,7 @@ var init_openai = __esm({
|
|
|
1784
1795
|
if (!process.env.OPENAI_API_KEY) {
|
|
1785
1796
|
throw new Error("OPENAI_API_KEY is not set. AI translation requires it; every other feature works offline.");
|
|
1786
1797
|
}
|
|
1787
|
-
|
|
1788
|
-
let OpenAICtor;
|
|
1789
|
-
try {
|
|
1790
|
-
const mod = require2("openai");
|
|
1791
|
-
OpenAICtor = mod.OpenAI ?? mod.default ?? mod;
|
|
1792
|
-
} catch {
|
|
1793
|
-
throw new Error('Provider "openai" requires the OpenAI SDK. Install it: npm i openai');
|
|
1794
|
-
}
|
|
1795
|
-
this.client = new OpenAICtor({ baseURL: config.endpoint ?? void 0 });
|
|
1798
|
+
this.client = loadOpenAIClient({ baseURL: config.endpoint ?? void 0 });
|
|
1796
1799
|
}
|
|
1797
1800
|
config;
|
|
1798
1801
|
client;
|
|
@@ -1985,6 +1988,34 @@ var init_bedrock = __esm({
|
|
|
1985
1988
|
}
|
|
1986
1989
|
});
|
|
1987
1990
|
|
|
1991
|
+
// src/server/ai/openrouter.ts
|
|
1992
|
+
function openRouterClientOptions(config) {
|
|
1993
|
+
const apiKey = process.env.OPENROUTER_API_KEY;
|
|
1994
|
+
if (!apiKey) {
|
|
1995
|
+
throw new Error("OPENROUTER_API_KEY is not set. AI translation requires it; every other feature works offline.");
|
|
1996
|
+
}
|
|
1997
|
+
return {
|
|
1998
|
+
apiKey,
|
|
1999
|
+
baseURL: config.endpoint ?? OPENROUTER_BASE_URL,
|
|
2000
|
+
defaultHeaders: { "HTTP-Referer": OPENROUTER_REFERER, "X-Title": OPENROUTER_TITLE }
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
var OPENROUTER_BASE_URL, OPENROUTER_REFERER, OPENROUTER_TITLE, OpenRouterProvider;
|
|
2004
|
+
var init_openrouter = __esm({
|
|
2005
|
+
"src/server/ai/openrouter.ts"() {
|
|
2006
|
+
"use strict";
|
|
2007
|
+
init_openai();
|
|
2008
|
+
OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
2009
|
+
OPENROUTER_REFERER = "https://www.npmjs.com/package/glotfile";
|
|
2010
|
+
OPENROUTER_TITLE = "glotfile";
|
|
2011
|
+
OpenRouterProvider = class extends OpenAIProvider {
|
|
2012
|
+
constructor(config, client) {
|
|
2013
|
+
super(config, client ?? loadOpenAIClient(openRouterClientOptions(config)));
|
|
2014
|
+
}
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
});
|
|
2018
|
+
|
|
1988
2019
|
// src/server/ai/index.ts
|
|
1989
2020
|
function makeProvider(config) {
|
|
1990
2021
|
const ai = config.ai;
|
|
@@ -1995,8 +2026,10 @@ function makeProvider(config) {
|
|
|
1995
2026
|
return new OpenAIProvider(ai);
|
|
1996
2027
|
case "bedrock":
|
|
1997
2028
|
return new BedrockProvider(ai);
|
|
2029
|
+
case "openrouter":
|
|
2030
|
+
return new OpenRouterProvider(ai);
|
|
1998
2031
|
default:
|
|
1999
|
-
throw new Error(`Unknown AI provider "${String(ai.provider)}". Supported: anthropic, openai, bedrock.`);
|
|
2032
|
+
throw new Error(`Unknown AI provider "${String(ai.provider)}". Supported: anthropic, openai, bedrock, openrouter.`);
|
|
2000
2033
|
}
|
|
2001
2034
|
}
|
|
2002
2035
|
var init_ai = __esm({
|
|
@@ -2005,6 +2038,7 @@ var init_ai = __esm({
|
|
|
2005
2038
|
init_anthropic();
|
|
2006
2039
|
init_openai();
|
|
2007
2040
|
init_bedrock();
|
|
2041
|
+
init_openrouter();
|
|
2008
2042
|
}
|
|
2009
2043
|
});
|
|
2010
2044
|
|
package/dist/server/server.js
CHANGED
|
@@ -83,7 +83,7 @@ function isPluralForm(key) {
|
|
|
83
83
|
return PLURAL_CATEGORIES.includes(key) || EXACT_SELECTOR_RE.test(key);
|
|
84
84
|
}
|
|
85
85
|
var LOCALE_CASES = ["lower-hyphen", "lower-underscore", "bcp47-hyphen", "bcp47-underscore"];
|
|
86
|
-
var PROVIDERS = ["anthropic", "openai", "bedrock"];
|
|
86
|
+
var PROVIDERS = ["anthropic", "openai", "bedrock", "openrouter"];
|
|
87
87
|
var GlotfileError = class extends Error {
|
|
88
88
|
};
|
|
89
89
|
function isObject(v) {
|
|
@@ -2517,6 +2517,17 @@ var AnthropicProvider = class {
|
|
|
2517
2517
|
|
|
2518
2518
|
// src/server/ai/openai.ts
|
|
2519
2519
|
import { createRequire } from "module";
|
|
2520
|
+
function loadOpenAIClient(opts) {
|
|
2521
|
+
const require2 = createRequire(import.meta.url);
|
|
2522
|
+
let OpenAICtor;
|
|
2523
|
+
try {
|
|
2524
|
+
const mod = require2("openai");
|
|
2525
|
+
OpenAICtor = mod.OpenAI ?? mod.default ?? mod;
|
|
2526
|
+
} catch {
|
|
2527
|
+
throw new Error("The OpenAI SDK is required for this provider. Install it: npm i openai");
|
|
2528
|
+
}
|
|
2529
|
+
return new OpenAICtor(opts);
|
|
2530
|
+
}
|
|
2520
2531
|
var OpenAIProvider = class {
|
|
2521
2532
|
constructor(config, client) {
|
|
2522
2533
|
this.config = config;
|
|
@@ -2527,15 +2538,7 @@ var OpenAIProvider = class {
|
|
|
2527
2538
|
if (!process.env.OPENAI_API_KEY) {
|
|
2528
2539
|
throw new Error("OPENAI_API_KEY is not set. AI translation requires it; every other feature works offline.");
|
|
2529
2540
|
}
|
|
2530
|
-
|
|
2531
|
-
let OpenAICtor;
|
|
2532
|
-
try {
|
|
2533
|
-
const mod = require2("openai");
|
|
2534
|
-
OpenAICtor = mod.OpenAI ?? mod.default ?? mod;
|
|
2535
|
-
} catch {
|
|
2536
|
-
throw new Error('Provider "openai" requires the OpenAI SDK. Install it: npm i openai');
|
|
2537
|
-
}
|
|
2538
|
-
this.client = new OpenAICtor({ baseURL: config.endpoint ?? void 0 });
|
|
2541
|
+
this.client = loadOpenAIClient({ baseURL: config.endpoint ?? void 0 });
|
|
2539
2542
|
}
|
|
2540
2543
|
config;
|
|
2541
2544
|
client;
|
|
@@ -2718,6 +2721,27 @@ var BedrockProvider = class {
|
|
|
2718
2721
|
}
|
|
2719
2722
|
};
|
|
2720
2723
|
|
|
2724
|
+
// src/server/ai/openrouter.ts
|
|
2725
|
+
var OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
2726
|
+
var OPENROUTER_REFERER = "https://www.npmjs.com/package/glotfile";
|
|
2727
|
+
var OPENROUTER_TITLE = "glotfile";
|
|
2728
|
+
function openRouterClientOptions(config) {
|
|
2729
|
+
const apiKey = process.env.OPENROUTER_API_KEY;
|
|
2730
|
+
if (!apiKey) {
|
|
2731
|
+
throw new Error("OPENROUTER_API_KEY is not set. AI translation requires it; every other feature works offline.");
|
|
2732
|
+
}
|
|
2733
|
+
return {
|
|
2734
|
+
apiKey,
|
|
2735
|
+
baseURL: config.endpoint ?? OPENROUTER_BASE_URL,
|
|
2736
|
+
defaultHeaders: { "HTTP-Referer": OPENROUTER_REFERER, "X-Title": OPENROUTER_TITLE }
|
|
2737
|
+
};
|
|
2738
|
+
}
|
|
2739
|
+
var OpenRouterProvider = class extends OpenAIProvider {
|
|
2740
|
+
constructor(config, client) {
|
|
2741
|
+
super(config, client ?? loadOpenAIClient(openRouterClientOptions(config)));
|
|
2742
|
+
}
|
|
2743
|
+
};
|
|
2744
|
+
|
|
2721
2745
|
// src/server/ai/index.ts
|
|
2722
2746
|
function makeProvider(config) {
|
|
2723
2747
|
const ai = config.ai;
|
|
@@ -2728,8 +2752,10 @@ function makeProvider(config) {
|
|
|
2728
2752
|
return new OpenAIProvider(ai);
|
|
2729
2753
|
case "bedrock":
|
|
2730
2754
|
return new BedrockProvider(ai);
|
|
2755
|
+
case "openrouter":
|
|
2756
|
+
return new OpenRouterProvider(ai);
|
|
2731
2757
|
default:
|
|
2732
|
-
throw new Error(`Unknown AI provider "${String(ai.provider)}". Supported: anthropic, openai, bedrock.`);
|
|
2758
|
+
throw new Error(`Unknown AI provider "${String(ai.provider)}". Supported: anthropic, openai, bedrock, openrouter.`);
|
|
2733
2759
|
}
|
|
2734
2760
|
}
|
|
2735
2761
|
|