localize-ai 1.0.0 → 1.1.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/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +31 -4
- package/dist/generate.js.map +1 -1
- package/dist/loadConfig.d.ts.map +1 -1
- package/dist/loadConfig.js +32 -3
- package/dist/loadConfig.js.map +1 -1
- package/dist/scripts/translate.js +110 -11
- package/dist/scripts/translate.js.map +1 -1
- package/package.json +28 -25
- package/readme.md +10 -5
package/dist/generate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAIA,wBAAsB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAIA,wBAAsB,qBAAqB,kBA6C1C"}
|
package/dist/generate.js
CHANGED
|
@@ -3,14 +3,41 @@ import path from "path";
|
|
|
3
3
|
import { loadUserConfig } from "./loadConfig.js";
|
|
4
4
|
export async function generateRuntimeConfig() {
|
|
5
5
|
const config = await loadUserConfig();
|
|
6
|
-
//
|
|
6
|
+
// ✅ Required fields (fail fast)
|
|
7
|
+
if (!config.sourceLanguage) {
|
|
8
|
+
console.error("❌ Missing 'sourceLanguage'");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
if (!config.translationLanguages) {
|
|
12
|
+
console.error("❌ Missing 'translationLanguages'");
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
if (!config.provider) {
|
|
16
|
+
console.error("❌ Missing 'provider'");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
if (!config.apikey) {
|
|
20
|
+
console.error("❌ Missing 'apikey'");
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
// ✅ Normalize optional field
|
|
24
|
+
const context = typeof config.context === "string" ? config.context : "";
|
|
25
|
+
// ✅ Transform
|
|
7
26
|
const runtimeConfig = {
|
|
8
27
|
sourceLanguage: config.sourceLanguage,
|
|
9
28
|
supportedLangs: config.translationLanguages,
|
|
10
|
-
apikey: config.apikey
|
|
29
|
+
apikey: config.apikey,
|
|
30
|
+
provider: config.provider,
|
|
31
|
+
context,
|
|
11
32
|
};
|
|
12
33
|
const outputPath = path.resolve(process.cwd(), "localize.runtime.json");
|
|
13
|
-
|
|
14
|
-
|
|
34
|
+
try {
|
|
35
|
+
fs.writeFileSync(outputPath, JSON.stringify(runtimeConfig, null, 2));
|
|
36
|
+
console.log("✅ Config ready (localize.runtime.json)");
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
console.error("❌ Failed to write localize.runtime.json");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
15
42
|
}
|
|
16
43
|
//# sourceMappingURL=generate.js.map
|
package/dist/generate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;IAEtC,6BAA6B;
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,qBAAqB;IACzC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;IAEtC,gCAAgC;IAChC,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,6BAA6B;IAC/B,MAAM,OAAO,GACX,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,cAAc;IACd,MAAM,aAAa,GAAG;QACpB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,cAAc,EAAE,MAAM,CAAC,oBAAoB;QAC3C,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO;KACR,CAAC;IAEF,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,uBAAuB,CAAC,CAAC;IAExE,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
package/dist/loadConfig.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadConfig.d.ts","sourceRoot":"","sources":["../src/loadConfig.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"loadConfig.d.ts","sourceRoot":"","sources":["../src/loadConfig.ts"],"names":[],"mappings":"AAIA,wBAAsB,cAAc,iBA+CnC"}
|
package/dist/loadConfig.js
CHANGED
|
@@ -1,13 +1,42 @@
|
|
|
1
|
+
import fs from "fs";
|
|
1
2
|
import path from "path";
|
|
2
3
|
import { pathToFileURL } from "url";
|
|
3
4
|
export async function loadUserConfig() {
|
|
4
5
|
const configPath = path.resolve(process.cwd(), "localize.config.js");
|
|
6
|
+
// ✅ 1. File existence
|
|
7
|
+
if (!fs.existsSync(configPath)) {
|
|
8
|
+
console.error("❌ localize.config.js not found. Run: npx localize-ai init");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
5
11
|
try {
|
|
6
|
-
const
|
|
7
|
-
|
|
12
|
+
const configModule = await import(pathToFileURL(configPath).href);
|
|
13
|
+
const config = configModule.default;
|
|
14
|
+
// ✅ 2. Validate required fields (fail fast with exact reason)
|
|
15
|
+
if (!config?.sourceLanguage) {
|
|
16
|
+
throw new Error("Missing 'sourceLanguage'");
|
|
17
|
+
}
|
|
18
|
+
if (!config?.translationLanguages) {
|
|
19
|
+
throw new Error("Missing 'translationLanguages'");
|
|
20
|
+
}
|
|
21
|
+
if (!Array.isArray(config.translationLanguages)) {
|
|
22
|
+
throw new Error("'translationLanguages' must be an array");
|
|
23
|
+
}
|
|
24
|
+
if (config.translationLanguages.length === 0) {
|
|
25
|
+
throw new Error("'translationLanguages' cannot be empty");
|
|
26
|
+
}
|
|
27
|
+
if (!config?.provider) {
|
|
28
|
+
throw new Error("Missing 'provider'");
|
|
29
|
+
}
|
|
30
|
+
if (!["gemini", "openai"].includes(config.provider)) {
|
|
31
|
+
throw new Error(`Invalid provider '${config.provider}'`);
|
|
32
|
+
}
|
|
33
|
+
if (!config?.apikey) {
|
|
34
|
+
throw new Error("Missing 'apikey' (env variable name)");
|
|
35
|
+
}
|
|
36
|
+
return config;
|
|
8
37
|
}
|
|
9
38
|
catch (err) {
|
|
10
|
-
console.error(
|
|
39
|
+
console.error(`❌ ${err.message}`);
|
|
11
40
|
process.exit(1);
|
|
12
41
|
}
|
|
13
42
|
}
|
package/dist/loadConfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../src/loadConfig.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAErE,IAAI,CAAC;QACH,MAAM,
|
|
1
|
+
{"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../src/loadConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAErE,sBAAsB;IACtB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC;QAEpC,8DAA8D;QAC9D,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,oBAAoB,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,MAAM,CAAC,oBAAoB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,qBAAqB,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -2,7 +2,15 @@ import dotenv from "dotenv";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
5
|
+
import OpenAI from "openai";
|
|
5
6
|
dotenv.config({ path: path.resolve(process.cwd(), ".env") }); // ✅ USER ENV
|
|
7
|
+
const log = {
|
|
8
|
+
info: (msg) => console.log(`ℹ️ ${msg}`),
|
|
9
|
+
success: (msg) => console.log(`✅ ${msg}`),
|
|
10
|
+
error: (msg) => console.log(`❌ ${msg}`),
|
|
11
|
+
warn: (msg) => console.log(`⚠️ ${msg}`),
|
|
12
|
+
step: (msg) => console.log(`\n🚀 ${msg}`),
|
|
13
|
+
};
|
|
6
14
|
const ROOT = process.cwd();
|
|
7
15
|
const runtimeConfigPath = path.join(ROOT, "localize.runtime.json");
|
|
8
16
|
if (!fs.existsSync(runtimeConfigPath)) {
|
|
@@ -10,15 +18,42 @@ if (!fs.existsSync(runtimeConfigPath)) {
|
|
|
10
18
|
process.exit(1);
|
|
11
19
|
}
|
|
12
20
|
const runtimeConfig = JSON.parse(fs.readFileSync(runtimeConfigPath, "utf-8"));
|
|
13
|
-
const { sourceLanguage, supportedLangs, apikey } = runtimeConfig;
|
|
21
|
+
const { sourceLanguage, supportedLangs, apikey, provider, context } = runtimeConfig;
|
|
22
|
+
if (!sourceLanguage) {
|
|
23
|
+
log.error("sourceLanguage is required in localize.config.js");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
if (!supportedLangs || supportedLangs.length === 0) {
|
|
27
|
+
log.error("translationLanguages cannot be empty");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
if (!provider) {
|
|
31
|
+
log.error("provider (gemini/openai) is required");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
if (!apikey) {
|
|
35
|
+
log.error("apikey variable name is missing in config");
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
if (!["gemini", "openai"].includes(provider)) {
|
|
39
|
+
log.error(`Invalid provider: ${provider}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
14
42
|
const API_KEY = process.env[apikey];
|
|
15
43
|
if (!API_KEY) {
|
|
16
|
-
console.error(
|
|
44
|
+
console.error(`❌ ${provider.toUpperCase()} API KEY missing in .env`);
|
|
17
45
|
process.exit(1);
|
|
18
46
|
}
|
|
19
47
|
const genAI = new GoogleGenerativeAI(API_KEY);
|
|
48
|
+
const openai = new OpenAI({
|
|
49
|
+
apiKey: API_KEY,
|
|
50
|
+
});
|
|
20
51
|
const INPUT = path.join(ROOT, "cleaned_strings.json");
|
|
21
52
|
const OUTPUT = path.join(ROOT, "public", "translations.json");
|
|
53
|
+
if (!fs.existsSync(INPUT)) {
|
|
54
|
+
log.error("cleaned_strings.json not found. Run extraction first.");
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
22
57
|
const CHUNK_SIZE = 100;
|
|
23
58
|
function chunk(arr, size) {
|
|
24
59
|
const res = [];
|
|
@@ -45,6 +80,18 @@ You are a translation engine.
|
|
|
45
80
|
|
|
46
81
|
Translate ONLY the missing languages.
|
|
47
82
|
|
|
83
|
+
${context
|
|
84
|
+
? `Context (optional, use only if helpful):
|
|
85
|
+
"${context}"`
|
|
86
|
+
: ""}
|
|
87
|
+
|
|
88
|
+
Guidelines:
|
|
89
|
+
- Use the provided context ONLY if it improves translation quality
|
|
90
|
+
- Ignore the context if it is not relevant to the text
|
|
91
|
+
- Preserve meaning, tone, and intent of UI text
|
|
92
|
+
- Do NOT over-interpret context
|
|
93
|
+
- Keep translations natural and concise
|
|
94
|
+
|
|
48
95
|
Rules:
|
|
49
96
|
- Return ONLY valid JSON
|
|
50
97
|
- No explanation
|
|
@@ -62,13 +109,49 @@ ${JSON.stringify(chunk)}
|
|
|
62
109
|
}
|
|
63
110
|
async function translateChunk(model, chunkData, existing, supportedLangs) {
|
|
64
111
|
const prompt = buildPrompt(chunkData, existing, supportedLangs);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
112
|
+
// 🔥 GEMINI FLOW
|
|
113
|
+
if (provider === "gemini") {
|
|
114
|
+
const result = await model.generateContent(prompt);
|
|
115
|
+
const response = await result.response;
|
|
116
|
+
let text = response.text();
|
|
117
|
+
text = text.replace(/```json|```/g, "").trim();
|
|
118
|
+
return JSON.parse(text);
|
|
119
|
+
}
|
|
120
|
+
// 🔥 OPENAI FLOW
|
|
121
|
+
if (provider === "openai") {
|
|
122
|
+
const completion = await openai.chat.completions.create({
|
|
123
|
+
model: "gpt-4o-mini",
|
|
124
|
+
messages: [
|
|
125
|
+
{
|
|
126
|
+
role: "system",
|
|
127
|
+
content: "You are a translation engine. Return only valid JSON.",
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
role: "user",
|
|
131
|
+
content: prompt,
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
temperature: 0,
|
|
135
|
+
});
|
|
136
|
+
const choice = completion.choices?.[0];
|
|
137
|
+
if (!choice || !choice.message?.content) {
|
|
138
|
+
throw new Error("❌ Invalid response from OpenAI");
|
|
139
|
+
}
|
|
140
|
+
let text = choice.message.content;
|
|
141
|
+
if (!text) {
|
|
142
|
+
console.log("⚠️ Empty response from OpenAI");
|
|
143
|
+
}
|
|
144
|
+
text = text.replace(/```json|```/g, "").trim();
|
|
145
|
+
return JSON.parse(text);
|
|
146
|
+
}
|
|
147
|
+
throw new Error("Invalid provider");
|
|
70
148
|
}
|
|
71
149
|
async function run() {
|
|
150
|
+
const startTime = Date.now();
|
|
151
|
+
log.step("Starting localization pipeline");
|
|
152
|
+
log.info(`Provider: ${provider}`);
|
|
153
|
+
log.info(`Source Language: ${sourceLanguage}`);
|
|
154
|
+
log.info(`Target Languages: ${supportedLangs.join(", ")}`);
|
|
72
155
|
const model = genAI.getGenerativeModel({
|
|
73
156
|
model: "gemini-2.5-flash",
|
|
74
157
|
});
|
|
@@ -88,8 +171,15 @@ async function run() {
|
|
|
88
171
|
});
|
|
89
172
|
const chunks = chunk(filtered, CHUNK_SIZE);
|
|
90
173
|
let final = { ...existing };
|
|
174
|
+
function updateProgress(current, total) {
|
|
175
|
+
const percent = Math.floor((current / total) * 100);
|
|
176
|
+
const barLength = 20;
|
|
177
|
+
const filled = Math.floor((percent / 100) * barLength);
|
|
178
|
+
const bar = "█".repeat(filled) + "-".repeat(barLength - filled);
|
|
179
|
+
process.stdout.write(`\r⏳ Translating: [${bar}] ${percent}% (${current}/${total})`);
|
|
180
|
+
}
|
|
91
181
|
for (const [i, chunk] of chunks.entries()) {
|
|
92
|
-
|
|
182
|
+
updateProgress(i + 1, chunks.length);
|
|
93
183
|
try {
|
|
94
184
|
const res = await translateChunk(model, chunk, existing, supportedLangs);
|
|
95
185
|
for (const key in res) {
|
|
@@ -104,12 +194,21 @@ async function run() {
|
|
|
104
194
|
}
|
|
105
195
|
}
|
|
106
196
|
}
|
|
107
|
-
catch {
|
|
108
|
-
|
|
197
|
+
catch (err) {
|
|
198
|
+
log.error(`Chunk ${i + 1} failed`);
|
|
199
|
+
console.log(err?.message || err);
|
|
109
200
|
}
|
|
110
201
|
}
|
|
202
|
+
process.stdout.write("\n"); // move to next line after progress
|
|
111
203
|
fs.writeFileSync(OUTPUT, JSON.stringify(final, null, 2));
|
|
112
|
-
|
|
204
|
+
log.success("translations.json generated successfully!");
|
|
205
|
+
console.log("\n📊 Summary:");
|
|
206
|
+
console.log(` Total input strings: ${texts.length}`);
|
|
207
|
+
console.log(` Translated now: ${filtered.length}`);
|
|
208
|
+
console.log(` Total stored translations: ${Object.keys(final).length}`);
|
|
209
|
+
console.log(` Output: public/translations.json\n`);
|
|
210
|
+
const duration = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
211
|
+
console.log(`⏱ Completed in ${duration}s`);
|
|
113
212
|
}
|
|
114
213
|
run();
|
|
115
214
|
//# sourceMappingURL=translate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/scripts/translate.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/scripts/translate.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,54 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "localize-ai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "plug and play localization package",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"files": [
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
9
11
|
"module": "dist/index.js",
|
|
10
12
|
"exports": {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
},
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
16
18
|
"bin": {
|
|
17
19
|
"localize-ai": "dist/cli.js"
|
|
18
20
|
},
|
|
19
21
|
"scripts": {
|
|
20
|
-
|
|
22
|
+
"build": "tsc",
|
|
21
23
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
22
24
|
},
|
|
23
25
|
"keywords": [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
],
|
|
26
|
+
"localization",
|
|
27
|
+
"i18n",
|
|
28
|
+
"translation",
|
|
29
|
+
"react-i18n",
|
|
30
|
+
"ai-translation",
|
|
31
|
+
"gemini"
|
|
32
|
+
],
|
|
31
33
|
"author": "Parth Gupta",
|
|
32
34
|
"license": "MIT",
|
|
33
35
|
"dependencies": {
|
|
34
36
|
"@google/generative-ai": "^0.24.1",
|
|
35
|
-
"dotenv": "^17.3.1"
|
|
37
|
+
"dotenv": "^17.3.1",
|
|
38
|
+
"openai": "^6.33.0"
|
|
36
39
|
},
|
|
37
40
|
"peerDependencies": {
|
|
38
41
|
"react": ">=18"
|
|
39
42
|
},
|
|
40
43
|
"devDependencies": {
|
|
41
|
-
"typescript": "^5.9.3",
|
|
42
44
|
"@types/node": "^25.5.0",
|
|
43
45
|
"@types/react": "^19.2.14",
|
|
44
|
-
"react": "^19.2.4"
|
|
46
|
+
"react": "^19.2.4",
|
|
47
|
+
"typescript": "^5.9.3"
|
|
45
48
|
},
|
|
46
49
|
"repository": {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
},
|
|
50
|
-
"homepage": "https://github.com/Parth-Gupta05/localize-ai",
|
|
51
|
-
"bugs": {
|
|
52
|
-
|
|
53
|
-
}
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/Parth-Gupta05/localize-ai.git"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/Parth-Gupta05/localize-ai",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/Parth-Gupta05/localize-ai/issues"
|
|
56
|
+
}
|
|
54
57
|
}
|
package/readme.md
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
# 🚀 localize-ai
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
**Plug & Play AI-powered localization for React apps**
|
|
4
5
|
|
|
6
|
+
> Context-aware AI localization with multi-provider support ⚡
|
|
7
|
+
|
|
5
8
|
Automatically extract, translate, and serve multilingual UI — powered by AI ⚡
|
|
6
9
|
|
|
10
|
+
|
|
7
11
|
---
|
|
8
12
|
|
|
9
13
|
## ✨ Features
|
|
10
14
|
|
|
11
15
|
* 🔍 Auto-extract static text from your codebase (`t("...")`)
|
|
12
|
-
* 🌍 AI-powered translations (Gemini)
|
|
16
|
+
* 🌍 AI-powered translations (Gemini, Openai)
|
|
13
17
|
* ⚡ Incremental translation (only new strings + languages)
|
|
14
18
|
* 🧠 Zero config runtime (auto loads translations)
|
|
15
19
|
* ⚛️ React hooks + context out of the box
|
|
16
20
|
* 💸 Cost optimized (no re-translation of existing content)
|
|
21
|
+
* 🧠 Context-aware translations
|
|
17
22
|
|
|
18
23
|
---
|
|
19
24
|
|
|
@@ -34,8 +39,9 @@ npm install localize-ai
|
|
|
34
39
|
export default {
|
|
35
40
|
sourceLanguage: "en",
|
|
36
41
|
translationLanguages: ["hi", "fr"],
|
|
37
|
-
provider: "gemini",
|
|
38
|
-
apikey: "VITE_GEMINI_API_KEY"
|
|
42
|
+
provider: "gemini", // or "openai"
|
|
43
|
+
apikey: "VITE_GEMINI_API_KEY",
|
|
44
|
+
context: "E-commerce checkout UI for buying products"
|
|
39
45
|
};
|
|
40
46
|
```
|
|
41
47
|
|
|
@@ -110,7 +116,7 @@ function App() {
|
|
|
110
116
|
```tsx
|
|
111
117
|
const { setLang } = useTranslation();
|
|
112
118
|
|
|
113
|
-
setLang("
|
|
119
|
+
setLang("fr"); // switch language
|
|
114
120
|
```
|
|
115
121
|
|
|
116
122
|
---
|
|
@@ -188,7 +194,6 @@ npx localize-ai translate # extract + translate
|
|
|
188
194
|
## 🗺 Roadmap
|
|
189
195
|
|
|
190
196
|
* [ ] AST-based extraction (no regex)
|
|
191
|
-
* [ ] Multi-provider support (OpenAI, etc.)
|
|
192
197
|
* [ ] Lazy loading translations
|
|
193
198
|
* [ ] CLI UI improvements
|
|
194
199
|
|