π Automatic translation synchronization for your internationalization files
Translation Sync is a powerful Node.js package that automatically translates your JSON translation files when changes are detected. It watches your translation directory and keeps all language files synchronized by translating only the changed keys.
- π Automatic Translation: Instantly translates changes in your source language files
- π File Watching: Real-time monitoring of translation files for changes
- π― Smart Updates: Only translates changed keys, not entire files
- π Nested Objects: Supports complex nested translation structures
- π Free Translation: Uses Google Translate's free API
- πΎ Hash Tracking: Prevents unnecessary re-translations using content hashing
- π§ Configurable: Flexible configuration options
- π Verbose Logging: Optional detailed logging for debugging
npm install translation-syncconst TranslationSync = require("translation-sync");
const sync = new TranslationSync({
directory: "./translations",
sourceLanguage: "en",
targetLanguages: ["es", "fr", "de", "it"],
onTranslationComplete: (filename, changes) => {
console.log(
`β
Translated ${Object.keys(changes).length} changes in ${filename}`
);
},
});
// Initialize and start watching
async function start() {
await sync.init();
await sync.watch();
}
start();| Option | Type | Default | Description |
|---|---|---|---|
directory |
string | "./translations" |
Directory containing translation files |
sourceLanguage |
string | "en" |
Source language code (e.g., "en", "es") |
targetLanguages |
array | [] |
Array of target language codes |
onTranslationComplete |
function | () => {} |
Callback executed after translation completion |
silent |
boolean | false |
Suppress all console output |
verbose |
boolean | false |
Enable detailed translation logging |
Your translation files should follow this naming convention:
translations/
βββ en.json # Source language
βββ es.json # Spanish translations
βββ fr.json # French translations
βββ de.json # German translations
βββ .translation-hashes.json # Auto-generated hash file
{
"common": {
"buttons": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete"
},
"messages": {
"success": "Operation completed successfully",
"error": "An error occurred"
}
},
"navigation": {
"home": "Home",
"about": "About Us",
"contact": "Contact"
}
}Creates a new TranslationSync instance with the specified configuration options.
const sync = new TranslationSync({
directory: "./src/i18n",
sourceLanguage: "en",
targetLanguages: ["es", "fr", "de"],
verbose: true,
});Initializes the translation sync system, creates necessary directories, and loads existing hashes.
await sync.init();Starts watching the translation directory for file changes. Returns a chokidar watcher instance.
const watcher = await sync.watch();
// Stop watching when needed
watcher.close();Manually checks all translation files and translates any changes. Useful for one-time synchronization.
await sync.checkAndTranslate();const TranslationSync = require("translation-sync");
const sync = new TranslationSync({
directory: "./i18n",
sourceLanguage: "en",
targetLanguages: ["es", "fr", "de"],
verbose: true,
});
async function syncOnce() {
await sync.init();
await sync.checkAndTranslate();
console.log("Translation sync completed!");
}
syncOnce();const TranslationSync = require("translation-sync");
const sync = new TranslationSync({
directory: "./translations",
sourceLanguage: "en",
targetLanguages: ["es", "fr", "de"],
onTranslationComplete: (filename, changes) => {
// Custom notification logic
console.log(
`π ${filename} updated with ${Object.keys(changes).length} changes`
);
// Log specific changes
Object.entries(changes).forEach(([key, value]) => {
console.log(` ${key}: "${value}"`);
});
// Could send webhook, update database, etc.
},
verbose: true,
});
async function startWatching() {
await sync.init();
const watcher = await sync.watch();
console.log("Translation sync is now watching for changes...");
// Graceful shutdown
process.on("SIGINT", () => {
console.log("\nShutting down translation sync...");
watcher.close();
process.exit(0);
});
}
startWatching();const sync = new TranslationSync({
directory: "./translations",
sourceLanguage: "en",
targetLanguages: ["es", "fr"],
silent: true, // No console output except errors
});You can create custom scripts that integrate with your build process:
translate.js
const TranslationSync = require("translation-sync");
const sync = new TranslationSync({
directory: process.env.TRANSLATIONS_DIR || "./src/translations",
sourceLanguage: process.env.SOURCE_LANG || "en",
targetLanguages: (process.env.TARGET_LANGS || "es,fr,de").split(","),
verbose: process.argv.includes("--verbose"),
});
async function main() {
await sync.init();
if (process.argv.includes("--watch")) {
await sync.watch();
console.log("Watching for translation changes...");
} else {
await sync.checkAndTranslate();
console.log("Translation check completed.");
}
}
main().catch(console.error);package.json
{
"scripts": {
"translate": "node translate.js",
"translate:watch": "node translate.js --watch",
"translate:verbose": "node translate.js --verbose",
"prebuild": "npm run translate"
}
}The package supports any language code that Google Translate recognizes. Common language codes include:
en- Englishes- Spanishfr- Frenchde- Germanit- Italianpt- Portugueseru- Russianja- Japaneseko- Koreanzh- Chinesear- Arabic
For regional variants, use format like en-US, es-MX, zh-CN, etc.
- Hash Tracking: Content hashes are calculated for each translation file to detect changes
- Change Detection: Only modified keys are identified for translation
- Smart Translation: Changed keys are translated to all target languages
- File Updates: Target language files are updated with new translations
- Hash Updates: New hashes are stored to prevent re-translation
- Only changes in the source language file trigger translations
- The package uses Google Translate's unofficial API (free but with rate limits)
- Hash file (
.translation-hashes.json) should be included in version control - Nested object structures are fully supported
- Original formatting and key order are preserved
- Translation requests have a 5-second timeout
- The
getOldData()method is simplified in the current implementation
- Uses unofficial Google Translate API which may have rate limits
- No built-in retry mechanism for failed translations
- Simplified old data tracking (may not preserve complete change history)
- No built-in authentication for translation services
Contributions are welcome! Please feel free to submit issues and pull requests.
MIT License - see LICENSE file for details.
- Built with chokidar for file watching
- Uses Google Translate for free translation services
Made with β€οΈ for the international development community