Skip to content

Commit 547d698

Browse files
Merge branch 'main' into main
2 parents 013661d + 919d037 commit 547d698

38 files changed

Lines changed: 1954 additions & 763 deletions

content/banner.dark.png

-1.61 KB
Loading

i18n.lock

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
version: 1
22
checksums:
33
29ba5363b2b0f1cc53dd4a667d52f86e:
4-
md-section-0: 93f48a7bb94abe74e46afbc7a5b3e253
5-
md-section-1: 3620411d5d5269697098a2f48fd2300c
6-
md-section-2: eb15721f4377325b8a64dea0f17a72f0
7-
md-section-3: cf8a21e4c83c137124f41aa2a86a6079
8-
md-section-4: 894e1ef13294725c03168d9f805fab8c
9-
md-section-5: bd84bf8a5e87bff887a84135b7bafa90
10-
md-section-6: 70a57e8c1442871a6b0d3fd2d820ff89
11-
md-section-7: 7d3d675756bbddc8ee496dce08022027
12-
md-section-8: dcc90be77da35ad96b4479c2f4a4beb8
13-
md-section-9: e2c36c043b1acc8c382997262556b3bd
14-
md-section-10: b9e3ff36c6e347b874d27ae61a7bdd06
15-
md-section-11: abe59bab6da32419b929894bb2e99f98
16-
md-section-12: 4b3ff0e6be9e9225bb7dfb58e054701d
17-
md-section-13: 1e8667055ff27abe990690dcd44b9fd4
18-
md-section-14: 98722b9330d01727cf5fc81a36aad5f4
19-
md-section-15: f8c2f53155acc08b4ced42864d396221
20-
md-section-16: 8ad16307794a2555d2e67a1fee6b877b
4+
md-section-0: 86fec84d2e13b5c02b68be8ed6890c7b
5+
md-section-1: 4728a6287bfa989bd038a1427917764e
6+
md-section-2: e33cd9539da0b03b8e630f00c6497708
7+
md-section-3: 3620411d5d5269697098a2f48fd2300c
8+
md-section-4: 10921a1656fe70cee91794ef88b334bb
9+
md-section-5: 547902a82d48ac6ac19b63797a21b6e3
10+
md-section-6: 1439973e5f597922d3fa6ed72280280e
11+
md-section-7: d807b6dfe81b5dc694070761d5f84ff0
12+
md-section-8: e7881ae7cd5323a925de529e0455c464
13+
md-section-9: 75fd9ee4563cf5658cee2bd08cfac285
14+
md-section-10: 1d18b63126baa6ec29d364cd1fa43268
15+
md-section-11: 3735c646f4a45b76cfc8d17876ca9e78
16+
md-section-12: b9e3ff36c6e347b874d27ae61a7bdd06
17+
md-section-13: 296b62b8246655783abb052076e160ce
18+
md-section-14: 9f9f799b09b5a2bdad13a45e5ba3cfd6
19+
md-section-15: cf8a21e4c83c137124f41aa2a86a6079
20+
md-section-16: 894e1ef13294725c03168d9f805fab8c
21+
md-section-17: e4ca514290d47807ca29bf363e2639e5
22+
md-section-18: cbdbf52703540c2e975e7858e90dd1f5
23+
md-section-19: abe59bab6da32419b929894bb2e99f98
24+
md-section-20: c7c8e3f78f4ab34b30dc0c2532f17898
25+
md-section-21: f8c2f53155acc08b4ced42864d396221
26+
md-section-22: 8ad16307794a2555d2e67a1fee6b877b

packages/cli/CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,37 @@
11
# lingo.dev
22

3+
## 0.80.1
4+
5+
### Patch Changes
6+
7+
- [`fb450cb`](https://github.com/lingodotdev/lingo.dev/commit/fb450cb2e90dd67ec008691a03237bdeecce5807) Thanks [@maxprilutskiy](https://github.com/maxprilutskiy)! - upd banner message
8+
9+
## 0.80.0
10+
11+
### Minor Changes
12+
13+
- [#614](https://github.com/lingodotdev/lingo.dev/pull/614) [`2495afd`](https://github.com/lingodotdev/lingo.dev/commit/2495afd69e23700f96e19e5bbf74e393b29c2033) Thanks [@maxprilutskiy](https://github.com/maxprilutskiy)! - add basic translators
14+
15+
### Patch Changes
16+
17+
- [#616](https://github.com/lingodotdev/lingo.dev/pull/616) [`516a79c`](https://github.com/lingodotdev/lingo.dev/commit/516a79c75501c5960ae944379f38591806ca43e2) Thanks [@mathio](https://github.com/mathio)! - po files --frozen flag
18+
19+
- Updated dependencies [[`2495afd`](https://github.com/lingodotdev/lingo.dev/commit/2495afd69e23700f96e19e5bbf74e393b29c2033), [`516a79c`](https://github.com/lingodotdev/lingo.dev/commit/516a79c75501c5960ae944379f38591806ca43e2), [`2cc6114`](https://github.com/lingodotdev/lingo.dev/commit/2cc61140fccc69ab73d40c7802a2d0e018889475)]:
20+
- @lingo.dev/_spec@0.27.0
21+
- @lingo.dev/_sdk@0.7.31
22+
23+
## 0.79.5
24+
25+
### Patch Changes
26+
27+
- [#612](https://github.com/lingodotdev/lingo.dev/pull/612) [`e541a12`](https://github.com/lingodotdev/lingo.dev/commit/e541a12436eeb4947caa077143c0b6e00b07e9b0) Thanks [@mathio](https://github.com/mathio)! - inject locale
28+
29+
## 0.79.4
30+
31+
### Patch Changes
32+
33+
- [#610](https://github.com/lingodotdev/lingo.dev/pull/610) [`ad05fbf`](https://github.com/lingodotdev/lingo.dev/commit/ad05fbf11b737c17a7cf2861be23ab2bf1189b52) Thanks [@mathio](https://github.com/mathio)! - handle prettier plugins deps
34+
335
## 0.79.3
436

537
### Patch Changes

packages/cli/i18n.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
{
2-
"version": 1.2,
2+
"version": 1.5,
3+
"provider": {
4+
"id": "anthropic",
5+
"model": "claude-3-7-sonnet-latest",
6+
"prompt": "You're translating text from {source} to {target}."
7+
},
38
"locale": {
49
"source": "en",
510
"targets": ["es", "fr", "it", "de", "ar"]

packages/cli/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lingo.dev",
3-
"version": "0.79.3",
3+
"version": "0.80.1",
44
"description": "Lingo.dev CLI",
55
"private": false,
66
"publishConfig": {
@@ -57,13 +57,16 @@
5757
"author": "",
5858
"license": "Apache-2.0",
5959
"dependencies": {
60+
"@ai-sdk/anthropic": "^1.2.6",
61+
"@ai-sdk/openai": "^1.3.7",
6062
"@datocms/cma-client-node": "^3.4.0",
6163
"@gitbeaker/rest": "^39.34.3",
6264
"@inquirer/prompts": "^7.2.3",
6365
"@lingo.dev/_sdk": "workspace:*",
6466
"@lingo.dev/_spec": "workspace:*",
6567
"@modelcontextprotocol/sdk": "^1.5.0",
6668
"@paralleldrive/cuid2": "^2.2.2",
69+
"ai": "^4.3.2",
6770
"bitbucket": "^2.12.0",
6871
"chalk": "^5.4.1",
6972
"cors": "^2.8.5",
@@ -100,6 +103,7 @@
100103
"p-limit": "^6.2.0",
101104
"php-array-reader": "^2.1.2",
102105
"plist": "^3.1.0",
106+
"posthog-node": "^4.11.2",
103107
"prettier": "^3.4.2",
104108
"properties-parser": "^0.6.0",
105109
"slugify": "^1.6.6",

packages/cli/src/cli/cmd/i18n.ts

Lines changed: 23 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { bucketTypeSchema, I18nConfig, localeCodeSchema, resolveOverriddenLocale } from "@lingo.dev/_spec";
2-
import { LingoDotDevEngine } from "@lingo.dev/_sdk";
32
import { Command } from "interactive-commander";
43
import Z from "zod";
54
import _ from "lodash";
@@ -17,6 +16,9 @@ import inquirer from "inquirer";
1716
import externalEditor from "external-editor";
1817
import { cacheChunk, deleteCache, getNormalizedCache } from "../utils/cache";
1918
import updateGitignore from "../utils/update-gitignore";
19+
import createProcessor from "../processor";
20+
import { withExponentialBackoff } from "../utils/exp-backoff";
21+
import trackEvent from "../utils/observability";
2022

2123
export default new Command()
2224
.command("i18n")
@@ -60,6 +62,7 @@ export default new Command()
6062
}
6163

6264
let hasErrors = false;
65+
let authId: string | null = null;
6366
try {
6467
ora.start("Loading configuration...");
6568
const i18nConfig = getConfig();
@@ -72,8 +75,14 @@ export default new Command()
7275

7376
ora.start("Connecting to Lingo.dev Localization Engine...");
7477
const auth = await validateAuth(settings);
78+
authId = auth.id;
7579
ora.succeed(`Authenticated as ${auth.email}`);
7680

81+
trackEvent(authId, "cmd.i18n.start", {
82+
i18nConfig,
83+
flags,
84+
});
85+
7786
let buckets = getBuckets(i18nConfig!);
7887
if (flags.bucket?.length) {
7988
buckets = buckets.filter((bucket: any) => flags.bucket!.includes(bucket.type));
@@ -299,11 +308,13 @@ export default new Command()
299308
bucketOra.start(
300309
`[${sourceLocale} -> ${targetLocale}] [${Object.keys(processableData).length} entries] (0%) AI localization in progress...`,
301310
);
302-
const localizationEngine = createLocalizationEngineConnection({
311+
let processPayload = createProcessor(i18nConfig!.provider, {
303312
apiKey: settings.auth.apiKey,
304313
apiUrl: settings.auth.apiUrl,
305314
});
306-
const processedTargetData = await localizationEngine.process(
315+
processPayload = withExponentialBackoff(processPayload, 3, 1000);
316+
317+
const processedTargetData = await processPayload(
307318
{
308319
sourceLocale,
309320
sourceData,
@@ -390,11 +401,20 @@ export default new Command()
390401
if (flags.verbose) {
391402
ora.info("Cache file deleted.");
392403
}
404+
trackEvent(auth.id, "cmd.i18n.success", {
405+
i18nConfig,
406+
flags,
407+
});
393408
} else {
394409
ora.warn("Localization completed with errors.");
395410
}
396411
} catch (error: any) {
397412
ora.fail(error.message);
413+
414+
trackEvent(authId || "unknown", "cmd.i18n.error", {
415+
flags,
416+
error,
417+
});
398418
process.exit(1);
399419
}
400420
});
@@ -435,47 +455,6 @@ async function retryWithExponentialBackoff<T>(
435455
throw new Error("Unreachable code");
436456
}
437457

438-
function createLocalizationEngineConnection(params: { apiKey: string; apiUrl: string; maxRetries?: number }) {
439-
const engine = new LingoDotDevEngine({
440-
apiKey: params.apiKey,
441-
apiUrl: params.apiUrl,
442-
});
443-
444-
return {
445-
process: async (
446-
args: {
447-
sourceLocale: string;
448-
sourceData: Record<string, any>;
449-
processableData: Record<string, any>;
450-
targetLocale: string;
451-
targetData: Record<string, any>;
452-
},
453-
onProgress: (
454-
progress: number,
455-
sourceChunk: Record<string, string>,
456-
processedChunk: Record<string, string>,
457-
) => void,
458-
) => {
459-
return retryWithExponentialBackoff(
460-
() =>
461-
engine.localizeObject(
462-
args.processableData,
463-
{
464-
sourceLocale: args.sourceLocale,
465-
targetLocale: args.targetLocale,
466-
reference: {
467-
[args.sourceLocale]: args.sourceData,
468-
[args.targetLocale]: args.targetData,
469-
},
470-
},
471-
onProgress,
472-
),
473-
params.maxRetries ?? 3,
474-
);
475-
},
476-
};
477-
}
478-
479458
function parseFlags(options: any) {
480459
return Z.object({
481460
apiKey: Z.string().optional(),

packages/cli/src/cli/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ ${vice(
3131
}),
3232
)}
3333
34-
Website: https://lingo.dev
34+
⚡️ AI-powered open-source CLI for web & mobile localization.
35+
36+
Star the the repo :) https://github.com/LingoDotDev/lingo.dev
3537
`,
3638
)
3739
.version(`v${packageJson.version}`, "-v, --version", "Show version")

packages/cli/src/cli/loaders/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ export default function createBucketLoader(
9494
createPoLoader(),
9595
createFlatLoader(),
9696
createSyncLoader(),
97-
createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys),
9897
createVariableLoader({ type: "python" }),
98+
createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys),
9999
);
100100
case "properties":
101101
return composeLoaders(
@@ -127,8 +127,8 @@ export default function createBucketLoader(
127127
createXcodeXcstringsLoader(options.defaultLocale),
128128
createFlatLoader(),
129129
createSyncLoader(),
130-
createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys),
131130
createVariableLoader({ type: "ieee" }),
131+
createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys),
132132
);
133133
case "yaml":
134134
return composeLoaders(

packages/cli/src/cli/loaders/inject-locale.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,17 @@ export default function createInjectLocaleLoader(
2020
if (!injectLocaleKeys) {
2121
return data;
2222
}
23+
24+
// ensures locale keys are in correct position
25+
const mergedData = _.merge({}, originalInput, data);
26+
2327
injectLocaleKeys.forEach((key) => {
24-
if (_.get(originalInput, key) === originalLocale) {
25-
_.set(data, key, locale);
28+
if (_.get(mergedData, key) === originalLocale) {
29+
_.set(mergedData, key, locale);
2630
}
2731
});
28-
return data;
32+
33+
return mergedData;
2934
},
3035
});
3136
}

packages/cli/src/cli/loaders/prettier.ts

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,21 @@ export default function createPrettierLoader(options: PrettierLoaderOptions): IL
3939
};
4040

4141
try {
42+
// format with prettier
4243
const result = await prettier.format(data, config);
4344
return result;
4445
} catch (error) {
4546
if (error instanceof Error && error.message.startsWith("Cannot find package")) {
4647
console.log();
47-
console.log("Prettier is missing some dependecies - installing all project dependencies");
48+
console.log("⚠️ Prettier plugins are not installed. Formatting without plugins.");
49+
console.log("⚠️ To use prettier plugins install project dependencies before running Lingo.dev.");
4850

49-
// prettier is missing dependencies - install all project dependencies
50-
installDependencies();
51+
config.plugins = [];
5152

52-
// clear file system structure cache to find newly installed dependencies
53+
// clear file system structure cache
5354
await prettier.clearConfigCache();
5455

55-
// try to format again
56+
// format again without plugins
5657
const result = await prettier.format(data, config);
5758
return result;
5859
} else {
@@ -71,31 +72,3 @@ async function loadPrettierConfig(filePath: string) {
7172
return {};
7273
}
7374
}
74-
75-
// install all dependencies using package manager
76-
async function installDependencies() {
77-
const packageManager = await getPackageManager();
78-
console.log(`Installing dependencies using ${packageManager}`);
79-
execSync(`${packageManager} install --frozen-lockfile`, { stdio: "inherit" });
80-
console.log(`Dependencies installed`);
81-
}
82-
83-
// determine if yarn or pnpm is used based on lockfile, otherwise use npm
84-
async function getPackageManager() {
85-
const yarnLockfile = path.resolve(process.cwd(), "yarn.lock");
86-
if (fs.existsSync(yarnLockfile)) {
87-
return "yarn";
88-
}
89-
90-
const pnpmLockfile = path.resolve(process.cwd(), "pnpm-lock.yaml");
91-
if (fs.existsSync(pnpmLockfile)) {
92-
return "pnpm";
93-
}
94-
95-
const bunLockfile = path.resolve(process.cwd(), "bun.lock");
96-
if (fs.existsSync(bunLockfile)) {
97-
return "bun";
98-
}
99-
100-
return "npm";
101-
}

0 commit comments

Comments
 (0)