Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

localize-ai

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

localize-ai - npm Package Compare versions

Comparing version
1.2.3
to
1.3.0
+2
dist/scripts/deleteSync.d.ts
export {};
//# sourceMappingURL=deleteSync.d.ts.map
{"version":3,"file":"deleteSync.d.ts","sourceRoot":"","sources":["../../src/scripts/deleteSync.ts"],"names":[],"mappings":""}
import fs from "fs";
import path from "path";
import * as parser from "@babel/parser";
import traverseModule from "@babel/traverse";
import * as t from "@babel/types";
const traverse = traverseModule.default;
const ROOT = process.cwd();
const SRC_DIR = path.join(ROOT, "src");
const EXTRACTED_FILE = path.join(ROOT, "extractedText.json");
const CLEANED_FILE = path.join(ROOT, "cleaned_strings.json");
// 👇 translations folder (you can adjust if needed)
const PUBLIC_DIR = path.join(ROOT, "public");
// 🔥 normalize (same as runtime)
function normalize(text) {
return text.trim();
}
// 🔥 collect current keys from AST
function extractKeys() {
const usedKeys = new Set();
function scanDir(dir) {
const files = fs.readdirSync(dir);
for (const file of files) {
const fullPath = path.join(dir, file);
if (fs.statSync(fullPath).isDirectory()) {
scanDir(fullPath);
}
else if (/\.(tsx|jsx|ts|js)$/.test(file)) {
const content = fs.readFileSync(fullPath, "utf-8");
try {
const ast = parser.parse(content, {
sourceType: "module",
plugins: ["jsx", "typescript"],
});
traverse(ast, {
CallExpression(path) {
const { callee, arguments: args } = path.node;
if (!t.isIdentifier(callee) || callee.name !== "t")
return;
const firstArg = args[0];
if (!firstArg)
return;
let value = null;
if (t.isStringLiteral(firstArg)) {
value = firstArg.value;
}
else if (t.isTemplateLiteral(firstArg)) {
if (firstArg.expressions.length > 0)
return;
value = firstArg.quasis
.map((q) => q.value.cooked || "")
.join("");
}
if (!value)
return;
usedKeys.add(normalize(value));
},
});
}
catch {
console.warn(`⚠️ Failed parsing ${fullPath}`);
}
}
}
}
scanDir(SRC_DIR);
return usedKeys;
}
// 🔥 remove unused keys from JSON file
function cleanJsonFile(filePath, usedKeys) {
if (!fs.existsSync(filePath))
return 0;
const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
let updated;
let removedCount = 0;
if (Array.isArray(data)) {
const before = data.length;
updated = data.filter((key) => usedKeys.has(normalize(key)));
removedCount = before - updated.length;
}
else {
const before = Object.keys(data).length;
updated = Object.fromEntries(Object.entries(data).filter(([key]) => usedKeys.has(normalize(key))));
const after = Object.keys(updated).length;
removedCount = before - after;
}
fs.writeFileSync(filePath, JSON.stringify(updated, null, 2));
return removedCount;
}
// 🔥 main runner
function run() {
console.log("🔍 Scanning codebase...");
const usedKeys = extractKeys();
console.log(`✅ Found ${usedKeys.size} active keys\n`);
let totalRemoved = 0;
function logResult(filePath, removed) {
const name = path.basename(filePath);
if (removed > 0) {
console.log(`🧹 ${name} → removed ${removed} keys`);
totalRemoved += removed;
}
else {
console.log(`✅ ${name} → no changes`);
}
}
// extracted files
logResult(EXTRACTED_FILE, cleanJsonFile(EXTRACTED_FILE, usedKeys));
logResult(CLEANED_FILE, cleanJsonFile(CLEANED_FILE, usedKeys));
// translations
if (fs.existsSync(PUBLIC_DIR)) {
const files = fs.readdirSync(PUBLIC_DIR);
files.forEach((file) => {
if (/^translations_.*\.json$/.test(file)) {
const fullPath = path.join(PUBLIC_DIR, file);
logResult(fullPath, cleanJsonFile(fullPath, usedKeys));
}
});
}
console.log("\n🚀 Delete sync completed!");
if (totalRemoved > 0) {
console.log(`🔥 Total removed keys: ${totalRemoved}`);
}
else {
console.log("✨ No unused keys found");
}
}
run();
//# sourceMappingURL=deleteSync.js.map
{"version":3,"file":"deleteSync.js","sourceRoot":"","sources":["../../src/scripts/deleteSync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,cAAc,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AAElC,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC;AAExC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAEvC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AAC7D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;AAE7D,oDAAoD;AACpD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAE7C,iCAAiC;AACjC,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACrB,CAAC;AAED,mCAAmC;AACnC,SAAS,WAAW;IAClB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,SAAS,OAAO,CAAC,GAAW;QAC1B,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAEtC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACpB,CAAC;iBAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAEnD,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE;wBAChC,UAAU,EAAE,QAAQ;wBACpB,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC;qBAC/B,CAAC,CAAC;oBAEH,QAAQ,CAAC,GAAG,EAAE;wBACZ,cAAc,CAAC,IAAS;4BACtB,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;4BAE9C,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,GAAG;gCAAE,OAAO;4BAE3D,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;4BACzB,IAAI,CAAC,QAAQ;gCAAE,OAAO;4BAEtB,IAAI,KAAK,GAAkB,IAAI,CAAC;4BAEhC,IAAI,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;gCAChC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;4BACzB,CAAC;iCAAM,IAAI,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;gCACzC,IAAI,QAAQ,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC;oCAAE,OAAO;gCAE5C,KAAK,GAAG,QAAQ,CAAC,MAAM;qCACpB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;qCAChC,IAAI,CAAC,EAAE,CAAC,CAAC;4BACd,CAAC;4BAED,IAAI,CAAC,KAAK;gCAAE,OAAO;4BAEnB,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;wBACjC,CAAC;qBACF,CAAC,CAAC;gBACL,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,CAAC,IAAI,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,uCAAuC;AACvC,SAAS,aAAa,CAAC,QAAgB,EAAE,QAAqB;IAC5D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,CAAC,CAAC;IAEvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;IAE5D,IAAI,OAAY,CAAC;IACjB,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE,CACpC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAC7B,CAAC;QAEF,YAAY,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACzC,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QAExC,OAAO,GAAG,MAAM,CAAC,WAAW,CAC1B,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CACpC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAC7B,CACF,CAAC;QAEF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QAC1C,YAAY,GAAG,MAAM,GAAG,KAAK,CAAC;IAChC,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAE7D,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,iBAAiB;AACjB,SAAS,GAAG;IACV,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAEvC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAE/B,OAAO,CAAC,GAAG,CAAC,WAAW,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC;IAEtD,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,SAAS,SAAS,CAAC,QAAgB,EAAE,OAAe;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAErC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,cAAc,OAAO,OAAO,CAAC,CAAC;YACpD,YAAY,IAAI,OAAO,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,eAAe,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,SAAS,CAAC,cAAc,EAAE,aAAa,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnE,SAAS,CAAC,YAAY,EAAE,aAAa,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE/D,eAAe;IACf,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAEzC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACrB,IAAI,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;gBAC7C,SAAS,CAAC,QAAQ,EAAE,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;YACzD,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAE3C,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,0BAA0B,YAAY,EAAE,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED,GAAG,EAAE,CAAC"}
+5
-0

@@ -12,2 +12,7 @@ #!/usr/bin/env node

}
else if (command === "delete-sync") {
const deletePath = path.join(__dirname, "scripts", "deleteSync.js");
execSync(`node "${deletePath}"`, { stdio: "inherit" });
console.log("✅ Done");
}
else if (command === "translate") {

@@ -14,0 +19,0 @@ console.log("🚀 Running localization pipeline...");

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;IACvB,qBAAqB,EAAE,CAAC;AAC1B,CAAC;KACI,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IAEnD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,sBAAsB,CAAC,CAAC;IAC1E,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAEtE,QAAQ,CAAC,SAAS,WAAW,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACxD,QAAQ,CAAC,SAAS,SAAS,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACtD,QAAQ,CAAC,SAAS,aAAa,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAE1D,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC;KACI,CAAC;IACJ,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AACnC,CAAC"}
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAC3C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;IACvB,qBAAqB,EAAE,CAAC;AAC1B,CAAC;KACI,IAAI,OAAO,KAAK,aAAa,EAAC,CAAC;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IACpE,QAAQ,CAAC,SAAS,UAAU,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAEvD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAExB,CAAC;KACI,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IAEnD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,sBAAsB,CAAC,CAAC;IAC1E,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAEtE,QAAQ,CAAC,SAAS,WAAW,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACxD,QAAQ,CAAC,SAAS,SAAS,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACtD,QAAQ,CAAC,SAAS,aAAa,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAE1D,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC;KACI,CAAC;IACJ,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AACnC,CAAC"}
export declare function useTranslation(): {
t: (key: string) => string;
t: (key: string, vars?: Record<string, any>) => string;
setLang: (lang: string) => void;

@@ -4,0 +4,0 @@ lang: string;

@@ -1,1 +0,1 @@

{"version":3,"file":"useTranslations.d.ts","sourceRoot":"","sources":["../../src/hooks/useTranslations.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc;aASZ,MAAM,KAAG,MAAM;;;;EAShC"}
{"version":3,"file":"useTranslations.d.ts","sourceRoot":"","sources":["../../src/hooks/useTranslations.ts"],"names":[],"mappings":"AASA,wBAAgB,cAAc;aA6BZ,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAG,MAAM;;;;EAY5D"}
import { useContext } from "react";
import LanguageContext from "../context/LanguageContext.js";
// 🔥 SAME NORMALIZER (IMPORTANT — MUST MATCH EXTRACTOR)
function normalize(text) {
return text
.trim();
}
export function useTranslation() {

@@ -9,10 +14,23 @@ const context = useContext(LanguageContext);

const { lang, translations, setLang, supportedLangs } = context;
function t(key) {
const entry = translations[key];
if (!entry)
return key;
return entry;
function interpolate(text, vars) {
if (!vars)
return text;
return text.replace(/{{(.*?)}}/g, (_, key) => {
const value = vars[key.trim()];
if (value === undefined) {
console.warn(`⚠️ Missing variable: ${key}`);
return `{{${key}}}`;
}
return String(value);
});
}
function t(key, vars) {
const normalizedKey = normalize(key);
const baseText = translations[normalizedKey] ||
translations[key] ||
key;
return interpolate(baseText, vars);
}
return { t, setLang, lang, supportedLangs };
}
//# sourceMappingURL=useTranslations.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"useTranslations.js","sourceRoot":"","sources":["../../src/hooks/useTranslations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,eAAe,MAAM,+BAA+B,CAAC;AAE5D,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IAE5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IAEhE,SAAS,CAAC,CAAC,GAAW;QACpB,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAEhC,IAAI,CAAC,KAAK;YAAE,OAAO,GAAG,CAAC;QAEvB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;AAC9C,CAAC"}
{"version":3,"file":"useTranslations.js","sourceRoot":"","sources":["../../src/hooks/useTranslations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,eAAe,MAAM,+BAA+B,CAAC;AAE5D,wDAAwD;AACxD,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI;SACR,IAAI,EAAE,CAAA;AACX,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IAE5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;IAEhE,SAAS,WAAW,CAClB,IAAY,EACZ,IAA0B;QAE1B,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YAE/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,CAAC,IAAI,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAC;gBAC5C,OAAO,KAAK,GAAG,IAAI,CAAC;YACtB,CAAC;YAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,CAAC,GAAW,EAAE,IAA0B;QAChD,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;QAErC,MAAM,QAAQ,GACZ,YAAY,CAAC,aAAa,CAAC;YAC3B,YAAY,CAAC,GAAG,CAAC;YACjB,GAAG,CAAC;QAEN,OAAO,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;AAC9C,CAAC"}

@@ -7,12 +7,8 @@ import fs from "fs";

function isValid(text) {
if (!text || text.length < 3)
if (!text || text.length < 2)
return false;
if (/^\d+$/.test(text))
return false;
if (text.includes("@"))
if (/^[A-Z0-9-_]+$/.test(text))
return false;
if (/^[^a-zA-Z]+$/.test(text))
return false;
if (text.includes("\\\\"))
return false;
return true;

@@ -19,0 +15,0 @@ }

@@ -1,1 +0,1 @@

{"version":3,"file":"cleanTranslations.js","sourceRoot":"","sources":["../../src/scripts/cleanTranslations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AACpD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;AAEvD,SAAS,OAAO,CAAC,IAAY;IAC3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,GAAG,GAAa,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAElE,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAEpC,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAE3D,OAAO,CAAC,GAAG,CAAC,sBAAsB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC"}
{"version":3,"file":"cleanTranslations.js","sourceRoot":"","sources":["../../src/scripts/cleanTranslations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AACpD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;AAEvD,SAAS,OAAO,CAAC,IAAY;IAC3B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,GAAG,GAAa,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAElE,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAEpC,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAE3D,OAAO,CAAC,GAAG,CAAC,sBAAsB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC"}
import fs from "fs";
import path from "path";
const ROOT = process.cwd(); // ✅ user project
import * as parser from "@babel/parser";
import traverseModule from "@babel/traverse";
import * as t from "@babel/types";
const traverse = traverseModule.default;
const ROOT = process.cwd();
const SRC_DIR = path.join(ROOT, "src");

@@ -11,2 +15,8 @@ const OUTPUT_FILE = path.join(ROOT, "extractedText.json");

const newStrings = new Set();
// 🔥 Normalize string (CRITICAL FIX)
function normalize(text) {
return text
.trim();
}
// 🔥 Relaxed validation (FIXED)
function isValidText(text) {

@@ -17,10 +27,56 @@ if (!text || text.length < 2)

return false;
if (text.includes("@"))
if (/^[A-Z0-9-_]+$/.test(text))
return false;
if (/^[A-Z0-9-]+$/.test(text))
return false;
if (/₹|\$|€/.test(text))
return false;
return true;
}
function extractFromAST(content, filePath) {
try {
const ast = parser.parse(content, {
sourceType: "module",
plugins: ["jsx", "typescript"],
});
traverse(ast, {
CallExpression(path) {
const { callee, arguments: args } = path.node;
if (!t.isIdentifier(callee) || callee.name !== "t")
return;
const firstArg = args[0];
if (!firstArg)
return;
let extractedValue = null;
// ✅ STRING LITERAL
if (t.isStringLiteral(firstArg)) {
extractedValue = firstArg.value;
}
// ✅ TEMPLATE LITERAL
else if (t.isTemplateLiteral(firstArg)) {
// ❌ BLOCK dynamic template usage (IMPORTANT)
if (firstArg.expressions.length > 0) {
console.error(`
❌ Invalid template literal detected
📄 File: ${filePath}
📍 Line: ${path.node.loc?.start.line}
💡 Code: t(\`...\${}\`)
👉 Fix: t("Text {{var}}", { var })
`);
return;
}
extractedValue = firstArg.quasis
.map((q) => q.value.cooked || "")
.join("");
}
if (!extractedValue)
return;
const normalizedText = normalize(extractedValue);
if (isValidText(normalizedText) &&
!existingStrings.has(normalizedText)) {
newStrings.add(normalizedText);
}
},
});
}
catch {
console.warn(`⚠️ Failed to parse: ${filePath}`);
}
}
function scanDir(dir) {

@@ -35,10 +91,3 @@ const files = fs.readdirSync(dir);

const content = fs.readFileSync(fullPath, "utf-8");
const regex = /t\(\s*["'`]([^"'`]+)["'`]\s*(?:,\s*[a-zA-Z0-9_.]+)?\s*\)/g;
let match;
while ((match = regex.exec(content)) !== null) {
const text = match[1].trim();
if (isValidText(text) && !existingStrings.has(text)) {
newStrings.add(text);
}
}
extractFromAST(content, fullPath);
}

@@ -45,0 +94,0 @@ }

@@ -1,1 +0,1 @@

{"version":3,"file":"extractText.js","sourceRoot":"","sources":["../../src/scripts/extractText.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,iBAAiB;AAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAC,oBAAoB,CAAC,CAAC;AAEzD,IAAI,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;AAExC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;IAC/B,eAAe,GAAG,IAAI,GAAG,CACvB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAClD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;AAErC,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,OAAO,CAAC,GAAW;IAC1B,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAElC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAEtC,IAAI,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YACxC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAEnD,MAAM,KAAK,GACT,2DAA2D,CAAC;YAE9D,IAAI,KAA6B,CAAC;YAExC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;gBAE9B,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBACpD,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACG,CAAC;IACH,CAAC;AACH,CAAC;AAED,OAAO,CAAC,OAAO,CAAC,CAAC;AAEjB,MAAM,OAAO,GAAG,CAAC,GAAG,eAAe,EAAE,GAAG,UAAU,CAAC,CAAC;AAEpD,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAEhE,OAAO,CAAC,GAAG,CAAC,WAAW,UAAU,CAAC,IAAI,cAAc,CAAC,CAAC"}
{"version":3,"file":"extractText.js","sourceRoot":"","sources":["../../src/scripts/extractText.ts"],"names":[],"mappings":"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"}
{
"name": "localize-ai",
"version": "1.2.3",
"version": "1.3.0",
"description": "AI-powered React localization with context-aware translations, multi-provider support, lazy loading, and per-locale splitting",

@@ -44,2 +44,5 @@ "main": "dist/index.js",

"dependencies": {
"@babel/parser": "^7.29.2",
"@babel/traverse": "^7.29.0",
"@babel/types": "^7.29.0",
"@google/generative-ai": "^0.24.1",

@@ -53,2 +56,3 @@ "dotenv": "^17.3.1",

"devDependencies": {
"@types/babel__traverse": "^7.28.0",
"@types/node": "^25.5.0",

@@ -55,0 +59,0 @@ "@types/react": "^19.2.14",

@@ -18,3 +18,5 @@ # localize-ai

### 🔧 Core
* 🔍 Auto-extract static text (`t("...")`)
* 🔍 AST-based extraction (no regex)
* 🧩 Supports template literals with variables
* 🧹 Removes unused (dead) translations automatically
* 🌍 AI-powered translations (OpenAI, Gemini)

@@ -51,2 +53,22 @@ * ⚡ Incremental translation (only new strings/languages)

### 🧠 Smart Extraction (AST-based)
Localize-ai uses AST parsing instead of regex, ensuring accurate extraction:
* Handles complex code patterns
* Supports template literals with variables
* Avoids false positives
Example:
```
t(`hello {{userName}}, your order {{id}} is ready`, {
userName,
id: orderId
});
```
👉 Variables are preserved and translated correctly.
---
## 📦 Installation

@@ -142,4 +164,7 @@

return <h1>{t("Hello world")}</h1>;
}
return (
<p>
{t("Welcome back, {{name}}!", { name: userName })}
</p>
)}
```

@@ -159,2 +184,18 @@

## 🧹 Dead Translation Cleanup
```
npx localize-ai delete-sync
```
Localize-ai automatically removes unused translations:
* Detects strings no longer present in code
* Cleans up translation files
Keeps JSON lean and optimized
👉 Prevents bloated translation files over time.
---
## 🧠 How it works

@@ -194,7 +235,3 @@

{
"Get started": {
"en": "Get started",
"hi": "शुरू करें",
"fr": "Commencer"
}
"Get started": "शुरू करें"
}

@@ -236,3 +273,3 @@ ```

### Core Improvements
* [ ] AST-based extraction (no regex)
* [x] AST-based extraction (no regex)
* [ ] Better error handling & retry logic for failed translations

@@ -239,0 +276,0 @@ * [ ] CLI UX improvements (spinners, better logs)