diff --git a/apps/web/src/components/commands.tsx b/apps/web/src/components/commands.tsx
index 688e6ad..6a4e508 100644
--- a/apps/web/src/components/commands.tsx
+++ b/apps/web/src/components/commands.tsx
@@ -186,7 +186,7 @@ export function Commands() {
step >= 5 ? "opacity-100" : "opacity-0",
)}
>
- ◇ Which OpenAI model should be used for translations?
+ ◇ Which provider would you like to use??
= 5 ? "opacity-100" : "opacity-0",
)}
>
- │ ● GPT-4 (Default)
+ │ ● OpenAI
= 5 ? "opacity-100" : "opacity-0",
)}
+ >
+ │ ○ Ollama
+
+ = 6 ? "opacity-100" : "opacity-0",
+ )}
+ >
+ ◇ Which model should be used for translations?
+
+ = 6 ? "opacity-100" : "opacity-0",
+ )}
+ >
+ │ ● GPT-4 (Default)
+
+ = 6 ? "opacity-100" : "opacity-0",
+ )}
>
│ ○ GPT-4 Turbo
= 5 ? "opacity-100" : "opacity-0",
+ step >= 6 ? "opacity-100" : "opacity-0",
)}
>
│ ○ GPT-4o
@@ -215,7 +239,7 @@ export function Commands() {
= 5 ? "opacity-100" : "opacity-0",
+ step >= 6 ? "opacity-100" : "opacity-0",
)}
>
│ ○ GPT-4o mini
@@ -223,7 +247,7 @@ export function Commands() {
= 5 ? "opacity-100" : "opacity-0",
+ step >= 6 ? "opacity-100" : "opacity-0",
)}
>
│ ○ GPT-3.5 Turbo
@@ -239,7 +263,7 @@ export function Commands() {
= 6 ? "opacity-100" : "opacity-0",
+ step >= 7 ? "opacity-100" : "opacity-0",
)}
>
└ Configuration file and language files created successfully!
diff --git a/bun.lockb b/bun.lockb
index cb4e14a..7d52417 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/examples/next-international/languine.config.mjs b/examples/next-international/languine.config.mjs
index 6959f7b..8ead710 100644
--- a/examples/next-international/languine.config.mjs
+++ b/examples/next-international/languine.config.mjs
@@ -1,5 +1,5 @@
export default {
- version: "1.0.0",
+ version: "0.5.5",
locale: {
source: "en",
targets: ["fr"],
@@ -9,7 +9,8 @@ export default {
include: ["locales/[locale].ts"],
},
},
- openai: {
- model: "gpt-4-turbo",
+ llm: {
+ provider: "ollama",
+ model: "mistral:latest",
},
};
diff --git a/examples/next-international/locales/en.ts b/examples/next-international/locales/en.ts
index 76ac4f9..ea6a941 100644
--- a/examples/next-international/locales/en.ts
+++ b/examples/next-international/locales/en.ts
@@ -1,7 +1,7 @@
export default {
hello: "Hello",
welcome: "Hello {name}!",
- "about.you": "Hello {name}! You have {age} yo",
+ "about.you": "Hello {name}! You have {age} years",
"scope.test": "A scope",
"scope.more.test": "A scope",
"scope.more.param": "A scope with {param}",
@@ -11,4 +11,5 @@ export default {
"missing.translation.in.fr": "This should work",
"cows#one": "A cow",
"cows#other": "{count} cows",
+ "languine.hello": "Hello Languine",
} as const;
diff --git a/examples/next-international/locales/fr.ts b/examples/next-international/locales/fr.ts
index 2fa9711..b7f1c51 100644
--- a/examples/next-international/locales/fr.ts
+++ b/examples/next-international/locales/fr.ts
@@ -1,14 +1,15 @@
export default {
hello: "Bonjour",
- welcome: "Bonjour {name} !",
- "about.you": "Bonjour {name} ! Tu as {age} ans",
- "scope.test": "Un domaine",
- "scope.more.test": "Un domaine",
- "scope.more.param": "Un domaine avec {param}",
- "scope.more.and.more.test": "Un domaine",
+ welcome: "Bonjour {name}!",
+ "about.you": "Bonjour {name}! Vous avez {age} ans",
+ "scope.test": "Un scope",
+ "scope.more.test": "Un scope",
+ "scope.more.param": "Un scope avec {param}",
+ "scope.more.and.more.test": "Un scope",
"scope.more.stars#one": "1 étoile sur GitHub",
"scope.more.stars#other": "{count} étoiles sur GitHub",
"missing.translation.in.fr": "Cela devrait fonctionner",
"cows#one": "Une vache",
"cows#other": "{count} vaches",
+ "languine.hello": "Hello Languine",
} as const;
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 94873c0..91c1fa4 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "languine",
- "version": "0.5.5",
+ "version": "0.5.6",
"type": "module",
"bin": "dist/index.js",
"main": "dist/index.js",
@@ -23,6 +23,8 @@
"diff": "^7.0.0",
"dotenv": "^16.4.7",
"simple-git": "^3.27.0",
+ "ollama": "^0.5.11",
+ "ollama-ai-provider": "^1.1.0",
"zod": "^3.24.1"
},
"devDependencies": {
diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts
index 5668958..e60484f 100644
--- a/packages/cli/src/commands/init.ts
+++ b/packages/cli/src/commands/init.ts
@@ -2,6 +2,8 @@ import { execSync } from "node:child_process";
import fs from "node:fs/promises";
import path from "node:path";
import { intro, outro, select, text } from "@clack/prompts";
+import { providers } from "../providers.js";
+import type { Provider } from "../types.js";
import { configPath } from "../utils.js";
export async function init() {
@@ -51,32 +53,48 @@ export async function init() {
],
})) as string;
+ const provider = (await select({
+ message: "Which provider would you like to use?",
+ options: Object.values(providers),
+ initialValue: "openai",
+ })) as Provider;
+
+ if (provider === "ollama") {
+ try {
+ const ollamaBinary = execSync("which ollama").toString().trim();
+ if (!ollamaBinary) {
+ outro("Ollama binary not found. Please install Ollama");
+ process.exit(1);
+ }
+ } catch (error) {
+ outro("Ollama binary not found. Please install Ollama");
+ process.exit(1);
+ }
+ }
+
+ const models = await providers[provider].getModels();
+
const model = (await select({
- message: "Which OpenAI model should be used for translations?",
- options: [
- { value: "gpt-4-turbo", label: "GPT-4 Turbo (Default)" },
- { value: "gpt-4", label: "GPT-4" },
- { value: "gpt-4o", label: "GPT-4o" },
- { value: "gpt-4o-mini", label: "GPT-4o mini" },
- { value: "gpt-3.5-turbo", label: "GPT-3.5 Turbo" },
- ],
- initialValue: "gpt-4-turbo",
+ message: "Which model should be used for translations?",
+ options: models,
})) as string;
const configContent = `export default {
version: "${require("../../package.json").version}",
locale: {
source: "${sourceLanguage}",
- targets: ${JSON.stringify(targetLanguages.split(",").map((l) => l.trim()))}
+ targets: ${JSON.stringify(targetLanguages.split(",").map((l) => l.trim()))},
},
files: {
${fileFormat}: {
- include: ["${filesDirectory}/[locale].${fileFormat}"]
- }
+ include: ["${filesDirectory}/[locale].${fileFormat}"],
+ },
+ },
+ llm: {
+ provider: "${provider}",
+ model: "${model}",
+ temperature: 0,
},
- openai: {
- model: "${model}"
- }
}`;
try {
diff --git a/packages/cli/src/commands/translate.ts b/packages/cli/src/commands/translate.ts
index 856f0d7..5805380 100644
--- a/packages/cli/src/commands/translate.ts
+++ b/packages/cli/src/commands/translate.ts
@@ -1,13 +1,28 @@
import fs from "node:fs/promises";
import path from "node:path";
-import { createOpenAI } from "@ai-sdk/openai";
+import { type OpenAIProvider, createOpenAI } from "@ai-sdk/openai";
import { intro, outro, spinner } from "@clack/prompts";
import chalk from "chalk";
+import { type OllamaProvider, createOllama } from "ollama-ai-provider";
import { simpleGit } from "simple-git";
import { getTranslator } from "../translators/index.js";
import type { PromptOptions, UpdateResult } from "../types.js";
+import type { Config, Provider } from "../types.js";
import { getApiKey, getConfig } from "../utils.js";
+const providersMap: Record = {
+ openai: createOpenAI({
+ apiKey: await getApiKey("OpenAI", "OPENAI_API_KEY"),
+ }),
+ ollama: createOllama(),
+};
+
+function getModel(config: Config) {
+ const provider = providersMap[config.llm.provider];
+
+ return provider(config.llm.model);
+}
+
export async function translate(targetLocale?: string, force = false) {
intro("Starting translation process...");
@@ -28,12 +43,7 @@ export async function translate(targetLocale?: string, force = false) {
const git = simpleGit();
- // Initialize OpenAI
- const openai = createOpenAI({
- apiKey: await getApiKey("OpenAI", "OPENAI_API_KEY"),
- });
-
- const model = openai(config.openai.model);
+ const model = getModel(config);
const s = spinner();
s.start("Checking for changes and translating to target locales...");
@@ -120,7 +130,12 @@ export async function translate(targetLocale?: string, force = false) {
summary,
};
} catch (error) {
- return { locale, sourcePath, success: false, error };
+ return {
+ locale,
+ sourcePath,
+ success: false,
+ error,
+ };
}
}),
),
diff --git a/packages/cli/src/envs.ts b/packages/cli/src/envs.ts
new file mode 100644
index 0000000..7ff27f7
--- /dev/null
+++ b/packages/cli/src/envs.ts
@@ -0,0 +1,2 @@
+import dotenv from "dotenv";
+dotenv.config();
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index 4fea856..a1fdbaf 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -1,8 +1,6 @@
#!/usr/bin/env node
-import dotenv from "dotenv";
-dotenv.config();
-
+import "./envs.js";
import { select } from "@clack/prompts";
import chalk from "chalk";
import dedent from "dedent";
diff --git a/packages/cli/src/prompt.ts b/packages/cli/src/prompt.ts
index 19c6117..a929e48 100644
--- a/packages/cli/src/prompt.ts
+++ b/packages/cli/src/prompt.ts
@@ -8,7 +8,6 @@ Translation Requirements:
- Keep all technical identifiers unchanged
- Keep consistent capitalization, spacing, and line breaks
- Respect existing whitespace and newline patterns
-- Never add space before a ! or ?
`;
export function createBasePrompt(text: string, options: PromptOptions) {
diff --git a/packages/cli/src/providers.ts b/packages/cli/src/providers.ts
new file mode 100644
index 0000000..699cb67
--- /dev/null
+++ b/packages/cli/src/providers.ts
@@ -0,0 +1,50 @@
+import { outro } from "@clack/prompts";
+import chalk from "chalk";
+import ollama from "ollama";
+import type { Provider } from "./types.js";
+
+type ModelInfo = {
+ value: string;
+ label: string;
+};
+
+type ProviderConfig = {
+ value: Provider;
+ label: string;
+ getModels: () => Promise;
+};
+
+export const providers: Record = {
+ openai: {
+ value: "openai",
+ label: "OpenAI",
+ getModels: async () => [
+ { value: "gpt-4-turbo", label: "GPT-4 Turbo (Default)" },
+ { value: "gpt-4", label: "GPT-4" },
+ { value: "gpt-4o", label: "GPT-4o" },
+ { value: "gpt-4o-mini", label: "GPT-4o mini" },
+ { value: "gpt-3.5-turbo", label: "GPT-3.5 Turbo" },
+ ],
+ },
+ ollama: {
+ value: "ollama",
+ label: "Ollama",
+ getModels: async () => {
+ try {
+ const { models } = await ollama.list();
+
+ return models.map((model) => ({
+ value: model.name,
+ label: model.name,
+ }));
+ } catch {
+ outro(
+ chalk.red(
+ "Failed to get models from Ollama, is it installed and running?",
+ ),
+ );
+ process.exit(1);
+ }
+ },
+ },
+};
diff --git a/packages/cli/src/translators/js.ts b/packages/cli/src/translators/js.ts
index 67799ca..d5e8045 100644
--- a/packages/cli/src/translators/js.ts
+++ b/packages/cli/src/translators/js.ts
@@ -32,10 +32,13 @@ function getStrings(code: string) {
const strings: StringMatch[] = [];
while (match) {
- strings.push({
- index: match.index,
- content: match[0],
- });
+ // Skip if the string is a key (contains dots or #)
+ if (!match[0].includes(".") && !match[0].includes("#")) {
+ strings.push({
+ index: match.index,
+ content: match[0],
+ });
+ }
match = quotesRegex.exec(code);
}
@@ -52,11 +55,19 @@ function replaceStrings(
replaces.forEach((replace, i) => {
const original = strings[i];
+ if (!original) return; // Skip if no matching original string
+
const offset = out.length - code.length;
+ const quote = original.content[0]; // Get the quote character used
+
+ // Keep original quotes but ensure replacement content is complete
+ const wrappedReplace = replace.startsWith(quote)
+ ? replace
+ : `${quote}${replace}${quote}`;
out =
out.slice(0, original.index + offset) +
- replace +
+ wrappedReplace +
out.slice(original.index + original.content.length + offset);
});
@@ -96,12 +107,13 @@ export const javascript: Translator = {
const { object } = await generateObject({
model: options.model,
prompt: getPrompt(toTranslate, options),
+ temperature: options.config.llm?.temperature ?? 0,
schema: z.object({
- translations: z.array(z.string()),
+ items: z.array(z.string()),
}),
});
- translated = object.translations;
+ translated = object.items;
}
const output = replaceStrings(
@@ -129,13 +141,14 @@ export const javascript: Translator = {
const { object } = await generateObject({
model: options.model,
prompt: getPrompt(strings, options),
+ temperature: options.config.llm?.temperature ?? 0,
schema: z.object({
- translations: z.array(z.string()),
+ items: z.array(z.string()),
}),
});
return {
- content: replaceStrings(options.content, strings, object.translations),
+ content: replaceStrings(options.content, strings, object.items),
};
},
};
@@ -145,9 +158,9 @@ function getPrompt(strings: StringMatch[], options: PromptOptions) {
${baseRequirements}
- Preserve all object/property keys, syntax characters, and punctuation marks exactly
- Only translate text content within quotation marks
- - Don't remove the quotes around the keys and values
A list of javascript codeblocks, return the translated javascript string in a JSON array of string:`;
+
const codeblocks = strings
.map((v) => {
return `\`\`\`${options.format}\n${v.content}\n\`\`\``;
diff --git a/packages/cli/src/translators/json.ts b/packages/cli/src/translators/json.ts
index 026d6f0..e867f6b 100644
--- a/packages/cli/src/translators/json.ts
+++ b/packages/cli/src/translators/json.ts
@@ -13,6 +13,7 @@ export const json: Translator = {
if (changes.addedKeys.length > 0) {
translated = await generateObject({
model: options.model,
+ temperature: options.config.llm?.temperature ?? 0,
prompt: getPrompt(
JSON.stringify(
getContentToTranslate(sourceObj, changes.addedKeys),
@@ -43,6 +44,7 @@ export const json: Translator = {
const { object } = await generateObject({
model: options.model,
prompt: getPrompt(options.content, options),
+ temperature: options.config.llm?.temperature ?? 0,
output: "no-schema",
});
@@ -181,5 +183,6 @@ function getPrompt(json: string, options: PromptOptions) {
Source content (JSON), Return only the translated content with identical structure:
`;
+
return createBasePrompt(`${text}\n${json}`, options);
}
diff --git a/packages/cli/src/translators/md.ts b/packages/cli/src/translators/md.ts
index af7c2ee..5014410 100644
--- a/packages/cli/src/translators/md.ts
+++ b/packages/cli/src/translators/md.ts
@@ -42,6 +42,7 @@ export const markdown: Translator = {
const { object: arr } = await generateObject({
model: options.model,
+ temperature: options.config.llm?.temperature ?? 0,
schema: z.array(z.string()),
prompt: getPrompt(
`
diff --git a/packages/cli/src/types.ts b/packages/cli/src/types.ts
index cca29c3..cf687a7 100644
--- a/packages/cli/src/types.ts
+++ b/packages/cli/src/types.ts
@@ -1,5 +1,7 @@
import type { LanguageModelV1 } from "ai";
+export type Provider = "openai" | "ollama";
+
export interface Config {
version: string;
locale: {
@@ -11,8 +13,10 @@ export interface Config {
include: string[];
};
};
- openai: {
+ llm: {
+ provider: Provider;
model: string;
+ temperature: number;
};
instructions?: string;
hooks?: {
diff --git a/packages/cli/src/utils.ts b/packages/cli/src/utils.ts
index 8803322..b2b725e 100644
--- a/packages/cli/src/utils.ts
+++ b/packages/cli/src/utils.ts
@@ -28,7 +28,7 @@ export async function getApiKey(name: string, key: string) {
`)}
- by passing it inline:
${chalk.gray(`\`\`\`
- ${key}= npx cali
+ ${key}= npx languine
\`\`\`
`)}
- by setting it as an env variable in your shell (e.g. in ~/.zshrc or ~/.bashrc):
diff --git a/packages/cli/test/js.test.ts b/packages/cli/test/js.test.ts
index df6bbd6..d35cc3e 100644
--- a/packages/cli/test/js.test.ts
+++ b/packages/cli/test/js.test.ts
@@ -1,10 +1,10 @@
-import { expect, test } from "vitest";
-import { Config } from "../src/types.js";
import { readFile } from "node:fs/promises";
-import { fileURLToPath } from "node:url";
import path from "node:path";
+import { fileURLToPath } from "node:url";
import { MockLanguageModelV1 } from "ai/test";
+import { expect, test } from "vitest";
import { javascript } from "../src/translators/js.js";
+import type { Config } from "../src/types.js";
import { getPromptText } from "./test-utils.js";
const dir = path.dirname(fileURLToPath(import.meta.url));
@@ -29,13 +29,15 @@ test("JavaScript adapter: new", async () => {
rawCall: { rawPrompt: null, rawSettings: {} },
finishReason: "stop",
usage: { promptTokens: 10, completionTokens: 20 },
- text: JSON.stringify([
- '"标题"',
- '"介绍"',
- "'在开始之前,请确保您具备以下条件:\\n一个 GitHub 账户'",
- "`您可以在自己的云基础设施上自托管 Midday,以便更好地控制您的数据。\\n 本指南将引导您完成设置 Midday 的整个过程。`",
- "`当前时间是 ${Date.now()}`",
- ]),
+ text: JSON.stringify({
+ items: [
+ "标题",
+ "介绍",
+ "在开始之前,请确保您具备以下条件:\n一个 GitHub 账户",
+ "您可以在自己的云基础设施上自托管 Midday,以便更好地控制您的数据。\n 本指南将引导您完成设置 Midday 的整个过程。",
+ `当前时间是 ${Date.now()}`,
+ ],
+ }),
};
},
}),
@@ -70,12 +72,14 @@ test("JavaScript adapter: diff", async () => {
rawCall: { rawPrompt: null, rawSettings: {} },
finishReason: "stop",
usage: { promptTokens: 10, completionTokens: 20 },
- text: JSON.stringify([
- '"title"',
- '"Updated"',
- "`Updated\nUpdated`",
- "`Updated ${Date.now()}`",
- ]),
+ text: JSON.stringify({
+ items: [
+ "title",
+ "Updated",
+ "Updated\nUpdated",
+ `Updated ${Date.now()}`,
+ ],
+ }),
};
},
}),
diff --git a/packages/cli/test/json.test.ts b/packages/cli/test/json.test.ts
index 80a168e..fffd175 100644
--- a/packages/cli/test/json.test.ts
+++ b/packages/cli/test/json.test.ts
@@ -1,10 +1,10 @@
-import { expect, test } from "vitest";
-import { Config } from "../src/types.js";
import { readFile } from "node:fs/promises";
-import { fileURLToPath } from "node:url";
import path from "node:path";
+import { fileURLToPath } from "node:url";
import { MockLanguageModelV1 } from "ai/test";
+import { expect, test } from "vitest";
import { json } from "../src/translators/json.js";
+import type { Config } from "../src/types.js";
import { getPromptText } from "./test-utils.js";
const dir = path.dirname(fileURLToPath(import.meta.url));
diff --git a/packages/cli/test/md.test.ts b/packages/cli/test/md.test.ts
index b36f32a..b00e88d 100644
--- a/packages/cli/test/md.test.ts
+++ b/packages/cli/test/md.test.ts
@@ -1,11 +1,11 @@
-import { getPromptText } from "./test-utils.js";
-import { expect, test } from "vitest";
-import { markdown } from "../src/translators/md.js";
-import { Config } from "../src/types.js";
import { readFile } from "node:fs/promises";
-import { fileURLToPath } from "node:url";
import path from "node:path";
+import { fileURLToPath } from "node:url";
import { MockLanguageModelV1 } from "ai/test";
+import { expect, test } from "vitest";
+import { markdown } from "../src/translators/md.js";
+import type { Config } from "../src/types.js";
+import { getPromptText } from "./test-utils.js";
const dir = path.dirname(fileURLToPath(import.meta.url));
@@ -24,7 +24,7 @@ test("markdown adapter: new", async () => {
rawCall: { rawPrompt: null, rawSettings: {} },
finishReason: "stop",
usage: { promptTokens: 10, completionTokens: 20 },
- text: `你好,世界,这是一个用于测试翻译的测试文档。`,
+ text: "你好,世界,这是一个用于测试翻译的测试文档。",
}),
}),
});
diff --git a/packages/cli/test/snapshots/js-diff.js b/packages/cli/test/snapshots/js-diff.js
index 9706b34..fd1c3fd 100644
--- a/packages/cli/test/snapshots/js-diff.js
+++ b/packages/cli/test/snapshots/js-diff.js
@@ -6,5 +6,5 @@ export default {
content: `Updated
Updated`
},
- dynamic: `Updated ${Date.now()}`
+ dynamic: `Translated ${Date.now()}`
}
diff --git a/packages/cli/test/snapshots/js-diff.prompt.txt b/packages/cli/test/snapshots/js-diff.prompt.txt
index 4b88608..ee68166 100644
--- a/packages/cli/test/snapshots/js-diff.prompt.txt
+++ b/packages/cli/test/snapshots/js-diff.prompt.txt
@@ -8,7 +8,6 @@ Translation Requirements:
- Keep all technical identifiers unchanged
- Keep consistent capitalization, spacing, and line breaks
- Respect existing whitespace and newline patterns
-- Never add space before a ! or ?
- Preserve all object/property keys, syntax characters, and punctuation marks exactly
- Only translate text content within quotation marks
@@ -24,8 +23,4 @@ A list of javascript codeblocks, return the translated javascript string in a JS
```js
`Explore ideas and examples of
what you can build with the Midday API`
-```
-
-```js
-`the current time is not ${Date.now()}`
```
\ No newline at end of file
diff --git a/packages/cli/test/snapshots/js-new.js b/packages/cli/test/snapshots/js-new.js
index 3ff7bf9..9ce9917 100644
--- a/packages/cli/test/snapshots/js-new.js
+++ b/packages/cli/test/snapshots/js-new.js
@@ -1,9 +1,11 @@
export default {
"标题": "介绍",
- description: '在开始之前,请确保您具备以下条件:\n一个 GitHub 账户',
+ description: '在开始之前,请确保您具备以下条件:
+一个 GitHub 账户',
nested: {
- content: `您可以在自己的云基础设施上自托管 Midday,以便更好地控制您的数据。\n 本指南将引导您完成设置 Midday 的整个过程。`
+ content: `You can self-host Midday on your own cloud infrastructure for greater control over your data.
+ This guide will walk you through the entire process of setting up Midday.`
},
- dynamic: `当前时间是 ${Date.now()}`
+ dynamic: `the current time is ${Date.now()}`
}
diff --git a/packages/cli/test/snapshots/js-new.prompt.txt b/packages/cli/test/snapshots/js-new.prompt.txt
index c44866f..023fc74 100644
--- a/packages/cli/test/snapshots/js-new.prompt.txt
+++ b/packages/cli/test/snapshots/js-new.prompt.txt
@@ -8,7 +8,6 @@ Translation Requirements:
- Keep all technical identifiers unchanged
- Keep consistent capitalization, spacing, and line breaks
- Respect existing whitespace and newline patterns
-- Never add space before a ! or ?
- Preserve all object/property keys, syntax characters, and punctuation marks exactly
- Only translate text content within quotation marks
@@ -23,13 +22,4 @@ A list of javascript codeblocks, return the translated javascript string in a JS
```js
'Before you begin, make sure you have the following:\nA GitHub account'
-```
-
-```js
-`You can self-host Midday on your own cloud infrastructure for greater control over your data.
- This guide will walk you through the entire process of setting up Midday.`
-```
-
-```js
-`the current time is ${Date.now()}`
```
\ No newline at end of file
diff --git a/packages/cli/test/snapshots/json-diff.prompt.txt b/packages/cli/test/snapshots/json-diff.prompt.txt
index 654ae1e..78e4246 100644
--- a/packages/cli/test/snapshots/json-diff.prompt.txt
+++ b/packages/cli/test/snapshots/json-diff.prompt.txt
@@ -8,7 +8,6 @@ Translation Requirements:
- Keep all technical identifiers unchanged
- Keep consistent capitalization, spacing, and line breaks
- Respect existing whitespace and newline patterns
-- Never add space before a ! or ?
- Only translate text content within quotation marks
- Preserve all object/property keys, syntax characters, and punctuation marks exactly
- Retain all code elements like variables, functions, and control structures
diff --git a/packages/cli/test/snapshots/md-diff.prompt.txt b/packages/cli/test/snapshots/md-diff.prompt.txt
index 824c2a9..8ce8367 100644
--- a/packages/cli/test/snapshots/md-diff.prompt.txt
+++ b/packages/cli/test/snapshots/md-diff.prompt.txt
@@ -8,7 +8,6 @@ Translation Requirements:
- Keep all technical identifiers unchanged
- Keep consistent capitalization, spacing, and line breaks
- Respect existing whitespace and newline patterns
-- Never add space before a ! or ?
- Only translate frontmatter, and text content (including those in HTML/JSX)
- Keep original code comments, line breaks, code, and codeblocks
- Retain all code elements like variables, functions, and control structures