Skip to content

Commit 978b817

Browse files
SK8-infiCopilot
andauthored
feat(cli): lingo.dev init cursor Command for .cursorrules Setup (#1101) (#1409)
* feat: add init cursor command * feat: add init cursor command * feat: add init cursor command * Delete package-lock.json * Rename cursor.md to agents.md * Delete package-lock.json * feat(cli): lingo.dev init cursor Command for .cursorrules Setup (#1101) refactored * Delete agents.md * feat(cli): lingo.dev init cursor Command for .cursorrules Setup (#1101) changeset * feat(cli): lingo.dev init cursor Command for .cursorrules Setup (#1101) minor fixes * Update packages/cli/src/cli/cmd/init/cursor.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/cli/src/cli/cmd/init/cursor.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/cli/src/cli/cmd/init/cursor.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update packages/cli/src/cli/cmd/init/cursor.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Restore accidentally deleted file * Restore accidentally deleted file * Add i18n rules for Cursor AI agents * Update localization guidelines for Lingo.dev CLI Change after discussion with The-Best-Codes over Discord * Removing out of scope changes * remove out of scope changes * remove out of scope changes * feat(cli): add agents.md in package.json Signed-off-by: SK8-infi <shivansh.katiyar1712@gmail.com> * feat(cli): add agents.md in package.json Signed-off-by: SK8-infi <shivansh.katiyar1712@gmail.com> * Refactor path resolution for agents.md Updated path resolution for AGENTS_MD to handle both development and production environments. Was causing error of "agents.md not found" with help from @the_best_codes resolved the issue --------- Signed-off-by: SK8-infi <shivansh.katiyar1712@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 80cb380 commit 978b817

File tree

5 files changed

+81
-3
lines changed

5 files changed

+81
-3
lines changed

.changeset/nasty-nails-repair.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"lingo.dev": minor
3+
---
4+
5+
feat: add init cursor command for .cursorrules setup

packages/cli/agents.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Lingo.dev CLI Localization Guidelines
2+
3+
The following rules and guidelines should be followed to ensure effective AI-powered localization using the Lingo.dev CLI in projects using Lingo.dev:
4+
5+
1. **Structure content for translation**: Organize user-facing strings in supported formats (e.g., JSON locale files, ARB, PO, Markdown) to allow the Lingo.dev CLI to efficiently extract and translate content. Avoid hardcoding text directly in code where possible; use structured keys or files that the CLI can process.
6+
2. **Locale files**: Store source content and translations in locale-specific files or directories (e.g., `en.json`, `app/i18n/fr.json`). The Lingo.dev CLI will automatically generate and keep target locale files in sync by translating only new or changed content.
7+
3. **Source language as fallback**: Use a primary source language (usually English) as the base. The CLI treats your project files as the source of truth and provides fallbacks naturally through your runtime i18n setup for any missing translations.
8+
4. **Pluralization and formatting**: Use i18n formats and libraries that support pluralization, placeholders, and locale-specific date/number formatting (e.g., ICU MessageFormat). The CLI preserves these structures during AI translation for accurate results.
9+
5. **Avoid concatenation**: Do not concatenate translatable strings. Provide complete messages with interpolation placeholders so the AI translator can produce natural, contextually accurate results.
10+
6. **Contextual translations**: Add context or translator notes in your configuration (via buckets or comments in supported formats) for ambiguous terms. This helps the AI generate higher-quality translations.
11+
7. **Testing and review**: Run the Lingo.dev CLI regularly (e.g., in CI/CD) to generate translations, then test your application in multiple locales. Review AI-generated translations for accuracy and tone, using features like key locking to preserve approved versions.
12+
_For more details, refer to the Lingo.dev CLI documentation at lingo.dev or join the community Discord._

packages/cli/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@
113113
"files": [
114114
"bin",
115115
"build",
116-
"assets"
116+
"assets",
117+
"agents.md"
117118
],
118119
"scripts": {
119120
"lingo.dev": "node --inspect=9229 ./bin/cli.mjs",

packages/cli/src/cli/cmd/init.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { ensurePatterns } from "../utils/ensure-patterns";
1919
import updateGitignore from "../utils/update-gitignore";
2020
import initCICD from "../utils/init-ci-cd";
2121
import open from "open";
22+
import cursorInitCmd from "./init/cursor";
2223

2324
const openUrl = (path: string) => {
2425
const settings = getSettings(undefined);
@@ -116,8 +117,8 @@ export default new InteractiveCommand()
116117
throw new Error(`Invalid path: ${p}`);
117118
}
118119
}
119-
120120
return values;
121+
121122
})
122123
.prompt(undefined) // make non-interactive
123124
.default([]),
@@ -258,4 +259,5 @@ export default new InteractiveCommand()
258259
if (!isInteractive) {
259260
Ora().info("Please see https://lingo.dev/cli");
260261
}
261-
});
262+
})
263+
.addCommand(cursorInitCmd);
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { InteractiveCommand, InteractiveOption } from "interactive-commander";
2+
import Ora from "ora";
3+
import fs from "fs";
4+
import path from "path";
5+
import { fileURLToPath } from "url";
6+
import { confirm } from "@inquirer/prompts";
7+
8+
// Get the directory of this file
9+
const __filename = fileURLToPath(import.meta.url);
10+
const __dirname = path.dirname(__filename);
11+
// Access agents.md from package root (works in both dev and production)
12+
// Resolve from current file location: try both paths to handle dev and bundled environments
13+
const AGENTS_MD = fs.existsSync(path.resolve(__dirname, "../agents.md"))
14+
? path.resolve(__dirname, "../agents.md")
15+
: path.resolve(__dirname, "../../../../agents.md");
16+
// Create .cursorrules in user's current working directory
17+
const CURSORRULES = path.resolve(process.cwd(), ".cursorrules");
18+
19+
export default new InteractiveCommand()
20+
.command("cursor")
21+
.description("Initialize .cursorrules with i18n-specific instructions for Cursor AI.")
22+
.addOption(
23+
new InteractiveOption("-f, --force", "Overwrite .cursorrules without prompt.")
24+
.default(false)
25+
)
26+
.action(async (options) => {
27+
const spinner = Ora();
28+
// Read agents.md
29+
let template: string;
30+
try {
31+
template = fs.readFileSync(AGENTS_MD, "utf-8");
32+
} catch (err) {
33+
spinner.fail("Template file agents.md not found. Please reinstall the package.");
34+
return process.exit(1);
35+
}
36+
// Check for existing .cursorrules
37+
const exists = fs.existsSync(CURSORRULES);
38+
let shouldWrite;
39+
if (exists && !options.force) {
40+
shouldWrite = await confirm({
41+
message: ".cursorrules already exists. Overwrite?",
42+
});
43+
if (!shouldWrite) {
44+
spinner.info("Skipped: .cursorrules left unchanged.");
45+
return;
46+
}
47+
}
48+
try {
49+
fs.writeFileSync(CURSORRULES, template);
50+
spinner.succeed("Created .cursorrules");
51+
spinner.info(
52+
".cursorrules has been created with i18n-specific instructions for Cursor AI.",
53+
);
54+
} catch (err) {
55+
spinner.fail(`Failed to write .cursorrules: ${err}`);
56+
process.exit(1);
57+
}
58+
});

0 commit comments

Comments
 (0)