Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/send-metadata-to-endpoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"lingo.dev": patch
---

Send sessionId, triggerType, and file path metadata to the vNext localization endpoint
1 change: 1 addition & 0 deletions packages/cli/src/cli/cmd/run/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ function createWorkerTask(args: {
targetData: args.ctx.flags.force ? {} : targetData,
processableData,
hints: relevantHints,
filePath: assignedTask.bucketPathPattern,
},
async (progress, _sourceChunk, processedChunk) => {
// write translated chunks as they are received from LLM
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/cli/localizer/_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type LocalizerData = {
targetLocale: string;
targetData: Record<string, any>;
hints: Record<string, string[]>;
filePath?: string;
};

export type LocalizerProgressFn = (
Expand All @@ -16,7 +17,11 @@ export type LocalizerProgressFn = (
) => void;

export interface ILocalizer {
id: "Lingo.dev" | "Lingo.dev vNext" | "pseudo" | NonNullable<I18nConfig["provider"]>["id"];
id:
| "Lingo.dev"
| "Lingo.dev vNext"
| "pseudo"
| NonNullable<I18nConfig["provider"]>["id"];
checkAuth: () => Promise<{
authenticated: boolean;
username?: string;
Expand Down
38 changes: 26 additions & 12 deletions packages/cli/src/cli/localizer/lingodotdev-vnext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import { createId } from "@paralleldrive/cuid2";
* Creates a custom engine for Lingo.dev vNext that sends requests to:
* https://api.lingo.dev/process/<processId>/localize
*/
function createVNextEngine(config: { apiKey: string; apiUrl: string; processId: string }) {
function createVNextEngine(config: {
apiKey: string;
apiUrl: string;
processId: string;
sessionId: string;
triggerType: "cli" | "ci";
}) {
const endpoint = `${config.apiUrl}/process/${config.processId}/localize`;

return {
Expand All @@ -21,8 +27,8 @@ function createVNextEngine(config: { apiKey: string; apiUrl: string; processId:
reference?: Record<string, Record<string, any>>;
hints?: Record<string, string[]>;
},
workflowId: string,
fast: boolean,
filePath?: string,
signal?: AbortSignal,
): Promise<Record<string, string>> {
const res = await fetch(endpoint, {
Expand All @@ -33,12 +39,15 @@ function createVNextEngine(config: { apiKey: string; apiUrl: string; processId:
},
body: JSON.stringify(
{
params: { workflowId, fast },
params: { fast },
sourceLocale,
targetLocale,
data: payload.data,
reference: payload.reference,
hints: payload.hints,
sessionId: config.sessionId,
triggerType: config.triggerType,
metadata: filePath ? { filePath } : undefined,
},
null,
2,
Expand Down Expand Up @@ -69,7 +78,9 @@ function createVNextEngine(config: { apiKey: string; apiUrl: string; processId:
return jsonResponse.data || {};
},

async whoami(signal?: AbortSignal): Promise<{ email: string; id: string } | null> {
async whoami(
signal?: AbortSignal,
): Promise<{ email: string; id: string } | null> {
// vNext uses a simple response for whoami
return { email: "vnext-user", id: config.processId };
},
Expand All @@ -82,6 +93,7 @@ function createVNextEngine(config: { apiKey: string; apiUrl: string; processId:
fast?: boolean;
reference?: Record<string, Record<string, any>>;
hints?: Record<string, string[]>;
filePath?: string;
},
progressCallback?: (
progress: number,
Expand All @@ -93,7 +105,6 @@ function createVNextEngine(config: { apiKey: string; apiUrl: string; processId:
const chunkedPayload = extractPayloadChunks(obj);
const processedPayloadChunks: Record<string, string>[] = [];

const workflowId = createId();
for (let i = 0; i < chunkedPayload.length; i++) {
const chunk = chunkedPayload[i];
const percentageCompleted = Math.round(
Expand All @@ -104,8 +115,8 @@ function createVNextEngine(config: { apiKey: string; apiUrl: string; processId:
params.sourceLocale,
params.targetLocale,
{ data: chunk, reference: params.reference, hints: params.hints },
workflowId,
params.fast || false,
params.filePath,
signal,
);

Expand Down Expand Up @@ -158,10 +169,7 @@ function countWordsInRecord(
payload: any | Record<string, any> | Array<any>,
): number {
if (Array.isArray(payload)) {
return payload.reduce(
(acc, item) => acc + countWordsInRecord(item),
0,
);
return payload.reduce((acc, item) => acc + countWordsInRecord(item), 0);
} else if (typeof payload === "object" && payload !== null) {
return Object.values(payload).reduce(
(acc: number, item) => acc + countWordsInRecord(item),
Expand All @@ -186,8 +194,8 @@ export default function createLingoDotDevVNextLocalizer(
throw new Error(
dedent`
You're trying to use ${chalk.hex(colors.green)(
"Lingo.dev vNext",
)} provider, however, no API key is configured.
"Lingo.dev vNext",
)} provider, however, no API key is configured.

To fix this issue:
1. Set ${chalk.dim("LINGO_API_KEY")} environment variable, or
Expand All @@ -199,10 +207,15 @@ export default function createLingoDotDevVNextLocalizer(
// Use LINGO_API_URL from environment or default to api.lingo.dev
const apiUrl = process.env.LINGO_API_URL || "https://api.lingo.dev";

const sessionId = createId();
const triggerType = process.env.CI ? "ci" : "cli";

const engine = createVNextEngine({
apiKey,
apiUrl,
processId,
sessionId,
triggerType,
});

return {
Expand Down Expand Up @@ -236,6 +249,7 @@ export default function createLingoDotDevVNextLocalizer(
[input.targetLocale]: input.targetData,
},
hints: input.hints,
filePath: input.filePath,
},
onProgress,
);
Expand Down