@harshvz/lingodev-cli
v1.0.0
Published
CLI-based translation pipeline using lingo.dev SDK
Downloads
11
Readme
Lingo CLI - Translation Pipeline
A production-grade CLI tool for translating files using the lingo.dev JavaScript SDK.
🚀 Features
- Smart Path Handling: Translate single files, directories, or use
.for current directory - Format Preservation: Maintains formatting for Markdown, JSON, and text files
- Recursive Scanning: Automatically finds all supported files in directories
- Auto-detection: Source language can be auto-detected
- Safe Writing: Never overwrites existing files
- Comprehensive Reporting: Detailed progress and error reporting
- Clean Architecture: Service-based design for maintainability
📦 Installation
From Source
# Clone or navigate to the project
cd LingoDev
# Install dependencies
npm install
# Build the project
npm run build
# Link globally (optional)
npm linkFrom npm (when published)
npm install -g lingo-cli⚙️ Configuration
There are two ways to configure your API key:
1. Using CLI (Recommended)
You can save your API key globally using the CLI:
translate --set-key your_api_key_hereTo remove the saved key:
translate --reset-key2. Using Environment Variables
Create a .env file in the directory where you run the command:
LINGODOTDEV_API_KEY=your_api_key_hereOr set it in your terminal session:
export LINGODOTDEV_API_KEY=your_api_key_here🌍 Supported Languages
To see a list of all supported languages, run:
translate --languages
# or
translate -lThis will display all available language codes (e.g., en, hi, fr, ja) and their full names.
📖 Usage
Command Syntax
translate <path> [sourceLanguage] [targetLanguage]Arguments
| Argument | Description | Default | Required |
| ---------------- | ------------------------------------------------------ | ------- | -------- |
| path | File or directory path (use . for current directory) | - | ✓ |
| sourceLanguage | Source language code or auto | auto | ✗ |
| targetLanguage | Target language code | en | ✗ |
Flags
| Flag | Description |
| ------------------- | ------------------------------------ |
| --languages, -l | Show all supported language codes |
| --set-key | Save API key to global configuration |
| --reset-key | Remove saved API key |
| --help, -h | Show help message |
| --version, -v | Show version information |
Examples
# Translate all files in current directory to English (auto-detect source)
translate .
# Translate to Hindi (auto-detect source)
translate . auto hi
# Translate from Hindi to English
translate . hi en
# Translate a specific directory from French to English
translate ./docs fr en
# Translate a single file from Spanish to English
translate ./readme.md es enSupported File Types
| Extension | Description | Translation Behavior |
| --------- | ----------- | -------------------------------------------------- |
| .md | Markdown | Preserves formatting, code blocks remain unchanged |
| .json | JSON | Translates values only, keys remain unchanged |
| .txt | Plain text | Translates entire content |
Output Files
Translated files are saved with a language suffix:
file.md → file.en.md
data.json → data.en.json
readme.txt → readme.hi.txt🏗️ Architecture
The project follows a clean, service-based architecture:
src/
├── bin/
│ └── translate.ts # CLI entry point
├── services/
│ ├── CLIService.ts # Argument parsing & validation
│ ├── ConfigService.ts # Configuration management
│ ├── FileScannerService.ts # File system scanning
│ ├── TranslationService.ts # Translation logic
│ └── FileWriterService.ts # File writing
├── App.ts # Main orchestrator
└── index.ts # Package exportsService Responsibilities
1️⃣ CLIService
- Parses command-line arguments
- Validates paths and language codes
- Resolves
.toprocess.cwd() - Provides usage help
2️⃣ ConfigService
- Singleton pattern for configuration
- Reads environment variables
- Provides default settings
- Validates API configuration
3️⃣ FileScannerService
- Recursively scans directories
- Filters by supported file types
- Returns absolute file paths
4️⃣ TranslationService
- Wraps lingo.dev SDK
- Format-aware translation:
- Markdown: Preserves code blocks and formatting
- JSON: Translates values, keeps keys intact
- Text: Translates entire content
5️⃣ FileWriterService
- Generates localized filenames
- Safely writes files
- Prevents overwriting existing files
🎯 How It Works: translate . hi en
Let's trace through what happens when you run translate . hi en:
1. CLI Parsing (CLIService)
// Input: ['node', 'translate.js', '.', 'hi', 'en']
{
path: '/absolute/path/to/current/directory', // '.' resolved to process.cwd()
sourceLanguage: 'hi',
targetLanguage: 'en'
}2. File Scanning (FileScannerService)
// Recursively scans directory
[
"/absolute/path/readme.md",
"/absolute/path/data.json",
"/absolute/path/docs/guide.md",
];
// Only .md, .json, .txt files included3. Translation (TranslationService)
For each file:
// Read content
const content = await readFile(filePath);
// Translate based on file type
if (fileType === ".md") {
// Preserve markdown formatting, protect code blocks
translated = await translateMarkdown(content, "hi", "en");
} else if (fileType === ".json") {
// Translate values only, keep keys
translated = await translateJson(content, "hi", "en");
} else {
// Translate entire content
translated = await translateText(content, "hi", "en");
}4. File Writing (FileWriterService)
// Generate output filename
'readme.md' → 'readme.en.md'
'data.json' → 'data.en.json'
// Write to same directory
await writeFile(outputPath, translatedContent);5. Summary Report
═══════════════════════════════════════════════════════════
📊 Translation Summary
═══════════════════════════════════════════════════════════
✔ 8 file(s) translated
⚠ 3 file(s) skipped
❌ 1 file(s) failed
═══════════════════════════════════════════════════════════🔧 Development
Build
npm run buildWatch Mode
npm run devRun Locally
# After building
npm run translate -- . hi en
# Or use node directly
node dist/bin/translate.js . hi en🧪 Error Handling
The CLI handles various error scenarios:
- Invalid paths: Clear error message with path validation
- Empty directories: Warns when no supported files found
- Unsupported file types: Silently skips with summary
- SDK failures: Catches and reports translation errors
- File conflicts: Skips existing files to prevent overwrites
- Missing API key: Validates configuration before processing
📝 Example Output
🚀 Starting translation pipeline...
📁 Path: /Users/harsh/projects/docs
🌍 Translation: hi → en
🔍 Scanning for files...
✓ Found 5 file(s) to translate
📄 Processing: /Users/harsh/projects/docs/readme.md
📡 Translating: hi → en
✓ Saved to: /Users/harsh/projects/docs/readme.en.md
📄 Processing: /Users/harsh/projects/docs/data.json
📡 Translating: hi → en
✓ Saved to: /Users/harsh/projects/docs/data.en.json
═══════════════════════════════════════════════════════════
📊 Translation Summary
═══════════════════════════════════════════════════════════
✔ 5 file(s) translated
⚠ 0 file(s) skipped
❌ 0 file(s) failed
═══════════════════════════════════════════════════════════🔌 Integrating lingo.dev SDK
The current implementation includes a placeholder for the lingo.dev SDK. To integrate the actual SDK:
- Install the SDK:
npm install @lingo.dev/sdk- Update
TranslationService.ts:
import { LingoClient } from '@lingo.dev/sdk';
private async callLingoApi(
text: string,
sourceLanguage: string,
targetLanguage: string
): Promise<string> {
const client = new LingoClient({
apiKey: this.config.getApiKey()
});
const result = await client.translate({
text,
from: sourceLanguage,
to: targetLanguage
});
return result.translatedText;
}📄 License
MIT
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Built with ❤️ using TypeScript and lingo.dev
