{"id":43606894,"url":"https://github.com/atheodosiou/xlf-sync","last_synced_at":"2026-02-05T19:00:43.716Z","repository":{"id":335187003,"uuid":"1143761647","full_name":"atheodosiou/xlf-sync","owner":"atheodosiou","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-29T00:39:53.000Z","size":49,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-29T14:24:16.192Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atheodosiou.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-28T00:30:47.000Z","updated_at":"2026-01-29T00:39:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/atheodosiou/xlf-sync","commit_stats":null,"previous_names":["atheodosiou/xlf-sync"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/atheodosiou/xlf-sync","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atheodosiou%2Fxlf-sync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atheodosiou%2Fxlf-sync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atheodosiou%2Fxlf-sync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atheodosiou%2Fxlf-sync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atheodosiou","download_url":"https://codeload.github.com/atheodosiou/xlf-sync/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atheodosiou%2Fxlf-sync/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29130088,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T18:55:47.139Z","status":"ssl_error","status_checked_at":"2026-02-05T18:55:04.010Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-04T09:00:31.595Z","updated_at":"2026-02-05T19:00:43.706Z","avatar_url":"https://github.com/atheodosiou.png","language":"TypeScript","funding_links":["https://www.buymeacoffee.com/atheodosiou"],"categories":["Development Utilities"],"sub_categories":["Internationalization"],"readme":"# xlf-sync\n\n[![npm version](https://img.shields.io/npm/v/xlf-sync.svg?style=flat-square)](https://www.npmjs.com/package/xlf-sync)\n[![npm downloads](https://img.shields.io/npm/dm/xlf-sync.svg?style=flat-square)](https://www.npmjs.com/package/xlf-sync)\n[![github issues](https://img.shields.io/github/issues/atheodosiou/xlf-sync.svg?style=flat-square)](https://github.com/atheodosiou/xlf-sync/issues)\n[![license](https://img.shields.io/github/license/atheodosiou/xlf-sync.svg?style=flat-square)](https://github.com/atheodosiou/xlf-sync/blob/master/LICENSE)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)\n[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue?style=flat-square\u0026logo=typescript)](https://www.typescriptlang.org/)\n[![CI](https://github.com/atheodosiou/xlf-sync/actions/workflows/ci.yml/badge.svg)](https://github.com/atheodosiou/xlf-sync/actions/workflows/ci.yml)\n\n\u003e 📝 **Read the article:** [The Missing Piece in Angular i18n](https://dev.to/atheodosiou/the-missing-piece-in-angular-i18n-57m0)\n\n\u003e **The definitive CLI tool for synchronizing Angular XLIFF (1.2 \u0026 2.0) locale files.**\n\n**`xlf-sync`** is a robust, production-ready utility designed to solve the persistent challenge of Angular i18n management: keeping your locale files (`messages.\u003clocale\u003e.xlf`) in perfect sync with your source file (`messages.xlf`), without data loss or corruption.\n\nIt is built to integrate seamlessly into professional workflows, supporting both local development and strict CI/CD pipelines.\n\n[![xlf-sync](https://raw.githubusercontent.com/atheodosiou/xlf-sync/master/assets/landing_page.png)](https://atheodosiou.github.io/xlf-sync/)\n\n[**🌐 Visit the Official Landing Page \u0026 Documentation**](https://atheodosiou.github.io/xlf-sync/)\n\n---\n\n## 🚀 Why `xlf-sync`?\n\nIf you are coming from **`xliffmerge`** or **`ng-extract-i18n-merge`**, you'll find `xlf-sync` to be a modern, faster, and more reliable alternative.\n\n| Feature | `xlf-sync` | `xliffmerge` | `ng-extract-i18n-merge` |\n| :--- | :---: | :---: | :---: |\n| **XLIFF 1.2 \u0026 2.0** | ✅ Yes | ✅ Yes | ⚠️ Partial |\n| **Metadata Preservation** | ✅ Absolute | ⚠️ Limited | ⚠️ Limited |\n| **Visual Dashboard** | ✅ Yes | ❌ No | ❌ No |\n| **Zero Data Loss** | ✅ Guaranteed | ⚠️ Risky | ✅ Yes |\n| **Active Maintenance** | ✅ Active | ❌ Legacy | ✅ Active |\n\n\u003e [!TIP]\n\u003e **Migration follows a similar flow**: Simply point `xlf-sync` to your source and locale files. It will automatically detect your XLIFF version and merge without stripping your approved translations or translator notes.\n\n---\n\n## ✨ Key Features\n\n- **🔄 Full Synchronization**: Automatically adds missing keys from `messages.xlf` to all your locale files.\n- **🧠 Metadata Preservation**: Preserves all notes, context groups, and custom attributes (e.g., `approved=\"yes\"`) during sync. Zero data loss.\n- **🛡️ Data Safety**: Never overwrites existing translations. Your work is safe.\n- **🧬 Multi-Version Support**: Seamlessly handles **XLIFF 1.2** and **2.0** in the same project. It auto-detects the version per file.\n- **🧹 Auto-Sorting**: Reorders translations in locale files to match the source file's order, ensuring clean and readable diffs.\n- **💀 Graveyard Mode**: Optionally moves obsolete keys to a separate \"graveyard\" file instead of deleting them, preserving historical work.\n- **🤖 CI/CD Ready**: Dedicated `check` command with strict exit codes for your build pipelines.\n- **✨ Pretty Printing**: Normalizes XML formatting across all files, eliminating \"dirty\" diffs from other tools.\n\n---\n\n## 📦 Installation\n\nInstall globally or as a dev dependency in your project:\n\n```bash\nnpm install -D xlf-sync\n```\n\n```bash\nnpx xlf-sync --help\n```\n\n### 🎮 How it looks\n\n```text\n$ npx xlf-sync sync\n\n  xlf-sync v1.3.7\n  --------------------------------------------------\n  ✔ messages.xlf parsed (142 keys)\n  ✔ messages.el.xlf synced (+12 new, -3 obsolete)\n  ✔ messages.de.xlf synced (+12 new, -3 obsolete)\n  ✔ messages.fr.xlf synced (+12 new, -3 obsolete)\n  --------------------------------------------------\n  ✨ Done! Your locale files are in perfect sync.\n```\n\n---\n\n## 📂 Configuration\n\n![xlf-sync CLI](https://raw.githubusercontent.com/atheodosiou/xlf-sync/master/assets/cli.png)\n\nYou can avoid passing command-line arguments every time by creating an `xlf-sync.json` (or `xlf-sync.config.json`) file in your project root.\n\n### Example `xlf-sync.json`\n\n```json\n{\n  \"source\": \"src/locale/messages.xlf\",\n  \"locales\": \"src/locale/messages.*.xlf\",\n  \"sync\": {\n    \"newTarget\": \"todo\",\n    \"obsolete\": \"mark\",\n    \"dryRun\": false\n  },\n  \"check\": {\n    \"failOnMissing\": true,\n    \"verbose\": true\n  }\n}\n```\n\n### All Configuration Options\n\n| Option | JSON Key | Type | Description |\n| :--- | :--- | :--- | :--- |\n| **Global** | `source` | `string` | Path to source messages.xlf |\n| | `locales` | `string` | Glob for locale files |\n| **Sync** | `sync.newTarget` | `string` | `todo` \\| `empty` \\| `source` |\n| | `sync.obsolete` | `string` | `delete` \\| `mark` \\| `graveyard` |\n| | `sync.graveyardFile` | `string` | Path pattern for graveyard files |\n| | `sync.failOnMissing`| `boolean`| Exit non-zero on missing targets |\n| | `sync.dryRun` | `boolean`| Do not write files |\n| **Check** | `check.failOnMissing`| `boolean`| Exit non-zero on missing targets |\n| | `check.failOnObsolete`| `boolean`| Exit non-zero on obsolete keys |\n| | `check.failOnAdded` | `boolean`| Exit non-zero on un-synced keys |\n| | `check.newTarget` | `string` | `todo` \\| `empty` \\| `source` (for diff only) |\n| | `check.verbose` | `boolean`| Print missing keys list |\n\n\u003e [!TIP]\n\u003e **Precedence**: Command Line Flags **\u003e** `xlf-sync.json` **\u003e** Default Values.\n\n---\n\n## 🚀 Usage\n\n### 1. The `sync` Command\n\nThe core command to update your locale files. It reads the source file and updates all target locale files found by the glob pattern.\n\n```bash\n# Basic usage\nnpx xlf-sync sync \\\n  --source src/locale/messages.xlf \\\n  --locales \"src/locale/messages.*.xlf\"\n```\n\n#### Sync Options\n\n| Option | Default | Description |\n| :--- | :--- | :--- |\n| `--source \u003cpath\u003e` | `src/locale/messages.xlf` | Path to the source XLIFF file generated by `ng extract-i18n`. |\n| `--locales \u003cglob\u003e` | `src/locale/messages.*.xlf` | Glob pattern to find your target locale files (e.g., `src/locale/*.xlf`). |\n| `--new-target \u003cmode\u003e` | `todo` | **Strategy for new keys:**\u003cbr\u003e• `todo`: Fills target with `TODO`.\u003cbr\u003e• `empty`: Leaves target empty.\u003cbr\u003e• `source`: Copies source text to target. |\n| `--obsolete \u003cmode\u003e` | `mark` | **Strategy for removed source keys:**\u003cbr\u003e• `mark`: Keeps key with `state=\"obsolete\"` (or prefix).\u003cbr\u003e• `delete`: Permanently removes the key.\u003cbr\u003e• `graveyard`: Moves key to a separate file (see below). |\n| `--graveyard-file \u003cpattern\u003e` | `src/locale/_obsolete.{locale}.xlf` | Pattern for the output \"graveyard\" file. Used only if `--obsolete graveyard`. `{locale}` is replaced dynamically. |\n| `--fail-on-missing` | `false` | Exits with error (code 1) if any keys are missing translations. Useful if you want to enforce 100% translation coverage during sync. |\n| `--dry-run` | `false` | Simulates the operation without writing changes to disk. |\n\n---\n\n\n---\n\n### 2. The `report` Command\n\nGenerates a detailed console report about the translation coverage for each locale file. Useful for getting a quick overview of work remaining.\n\n```bash\nnpx xlf-sync report --source src/locale/messages.xlf --locales \"src/locale/messages.*.xlf\"\n```\n\n**Output Example:**\n```text\n┌────────┬─────┬──────┬────────────┬─────────┬────────┬───────┐\n│ Locale │ XLF │ Keys │ Translated │ Pending │ % Cov  │ Words │\n├────────┼─────┼──────┼────────────┼─────────┼────────┼───────┤\n│ de     │ 2.0 │ 120  │ 115        │ 5       │ 95.8%  │ 432   │\n│ fr     │ 2.0 │ 120  │ 40         │ 80      │ 33.3%  │ 150   │\n└────────┴─────┴──────┴────────────┴─────────┴────────┴───────┘\n```\n\n#### Report Options\n\n| Option | Default | Description |\n| :--- | :--- | :--- |\n| `--source \u003cpath\u003e` | `src/locale/messages.xlf` | Path to the source XLIFF file. |\n| `--locales \u003cglob\u003e` | `src/locale/messages.*.xlf` | Glob pattern for target locale files. |\n\n---\n\n### 3. The `dashboard` Command\n\nGenerates a modern, standalone **HTML dashboard** to visualize your translation progress with beautiful charts, tables, and an interactive translation matrix.\n\n```bash\nnpx xlf-sync dashboard --out report.html\n```\n\n![xlf-sync Dashboard](https://raw.githubusercontent.com/atheodosiou/xlf-sync/master/assets/dashboard.png)\n\n**Features:**\n- 📊 **Visual Statistics Cards**: Overview of locales, total keys, translated count, and pending translations\n- 📈 **Coverage Progress Bars**: Per-locale translation progress with percentage indicators\n- 🔍 **Translation Matrix**: Interactive table showing which keys exist in each locale\n  - ✅ Green checkmark for translated keys\n  - ❌ Red X for missing translations\n  - Search bar to filter by key ID\n- 🎨 **Modern UI**: Built with Tailwind CSS and Alpine.js for a premium, responsive experience\n- 📱 **Mobile-Friendly**: Fully responsive design that works on all devices\n\n#### Dashboard Options\n\n| Option | Default | Description |\n| :--- | :--- | :--- |\n| `--source \u003cpath\u003e` | `src/locale/messages.xlf` | Path to the source XLIFF file. |\n| `--locales \u003cglob\u003e` | `src/locale/messages.*.xlf` | Glob pattern for target locale files. |\n| `--out \u003cpath\u003e` | `xlf-report.html` | Path where the HTML file will be saved. |\n\n---\n\n### 4. The `check` Command\n\nA read-only command designed for **Continuous Integration (CI)** pipelines. It verifies the state of your translations without modifying any files.\n\n```bash\n# Check if files are in sync\nnpx xlf-sync check --fail-on-missing\n```\n\n#### Check Options\n\n| Option | Default | Description |\n| :--- | :--- | :--- |\n| `--source \u003cpath\u003e` | `src/locale/messages.xlf` | Path to the source XLIFF file. |\n| `--locales \u003cglob\u003e` | `src/locale/messages.*.xlf` | Glob pattern for target locale files. |\n| `--verbose` | `false` | Lists exactly which keys are missing or obsolete for each locale. |\n| `--fail-on-missing` | `false` | **CI Failure Condition**: Fail if any translation targets are missing or empty. |\n| `--fail-on-obsolete` | `false` | **CI Failure Condition**: Fail if obsolete keys exist in locale files. |\n| `--fail-on-added` | `false` | **CI Failure Condition**: Fail if new keys exist in source that haven't been synced to locales yet. |\n\n---\n\n## 📚 Advanced Workflows\n\n### Keeping Files Clean (Graveyard Mode)\n\nFor large, long-lived projects, we recommend the **Graveyard Strategy**. Instead of cluttering your main files with obsolete keys or deleting them immediately (and losing work), this mode moves them to a separate file.\n\n```bash\nnpx xlf-sync sync --obsolete graveyard\n```\n\n**Result:**\n- `messages.fr.xlf`: Contains **only** active, valid translations.\n- `_obsolete.fr.xlf`: Contains all retired keys. You can restore them later if needed.\n\n### Standard CI/CD Pipeline\n\nAdd this step to your Pull Request validation workflow to ensure no developer merges broken translations:\n\n```yaml\n- name: Verify i18n Sync\n  run: npx xlf-sync check --fail-on-missing --fail-on-added --verbose\n```\n\n---\n\n## 🛠️ Supported Formats\n\n| Format | Support Level |\n| :--- | :--- |\n| **XLIFF 1.2** | Legacy Angular projects. Supported fully. |\n| **XLIFF 2.0** | Modern Angular default. Supported fully. |\n| **Hybrid** | Mixed version projects are detecting and handled automatically per file. |\n\n---\n\n\n---\n\n## 🤝 Contributing\n\nWe welcome contributions! Whether it's bug reports, feature requests, or code contributions, your help is appreciated.\n\nPlease read our [Contributing Guidelines](https://github.com/atheodosiou/xlf-sync/blob/master/CONTRIBUTING.md) to get started.\n\n**Quick ways to contribute:**\n- ⭐ [Star the project](https://github.com/atheodosiou/xlf-sync) on GitHub\n- 🐛 [Report bugs](https://github.com/atheodosiou/xlf-sync/issues/new)\n- 💡 [Suggest features](https://github.com/atheodosiou/xlf-sync/issues/new)\n- 🔧 [Submit pull requests](https://github.com/atheodosiou/xlf-sync/pulls)\n\n\u003ca href=\"https://www.buymeacoffee.com/atheodosiou\" target=\"_blank\"\u003e\u003cimg src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" style=\"height: 60px !important;width: 217px !important;\" \u003e\u003c/a\u003e\n\n---\n\n## 📄 License\n\nMIT © [Anastasios Theodosiou](https://anastasios.theodosiou.me)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatheodosiou%2Fxlf-sync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatheodosiou%2Fxlf-sync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatheodosiou%2Fxlf-sync/lists"}