{"id":42985022,"url":"https://github.com/i18n-actions/ai-i18n","last_synced_at":"2026-02-23T04:34:14.998Z","repository":{"id":334990016,"uuid":"1142985958","full_name":"i18n-actions/ai-i18n","owner":"i18n-actions","description":"ai-i18n is a GitHub Action that translates your app's i18n files using LLMs. It extracts strings, translates only what's changed, and commits the results back to your repo. Works with your LLM provider (Anthropic, OpenAI, Ollama) and multiple i18n formats (XLIFF, JSON). A drop-in replacement for Lokalise, Phrase, and Crowdin.","archived":false,"fork":false,"pushed_at":"2026-02-10T03:55:49.000Z","size":8728,"stargazers_count":9,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-10T09:13:27.542Z","etag":null,"topics":["ai","angular","angular-i18n","anthropic","crowdin","github-actions","i18n","internationalization","llm","localization","lokalise","open-source","openai","phrase","react-intl","vue-i18n"],"latest_commit_sha":null,"homepage":"","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/i18n-actions.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-27T03:56:56.000Z","updated_at":"2026-02-10T03:54:22.000Z","dependencies_parsed_at":"2026-02-01T03:04:25.023Z","dependency_job_id":null,"html_url":"https://github.com/i18n-actions/ai-i18n","commit_stats":null,"previous_names":["i18n-actions/ai-i18n"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/i18n-actions/ai-i18n","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18n-actions%2Fai-i18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18n-actions%2Fai-i18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18n-actions%2Fai-i18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18n-actions%2Fai-i18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/i18n-actions","download_url":"https://codeload.github.com/i18n-actions/ai-i18n/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18n-actions%2Fai-i18n/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29738079,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T02:24:00.660Z","status":"ssl_error","status_checked_at":"2026-02-23T02:22:56.087Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6: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":["ai","angular","angular-i18n","anthropic","crowdin","github-actions","i18n","internationalization","llm","localization","lokalise","open-source","openai","phrase","react-intl","vue-i18n"],"created_at":"2026-01-31T02:16:48.860Z","updated_at":"2026-02-23T04:34:14.964Z","avatar_url":"https://github.com/i18n-actions.png","language":"TypeScript","funding_links":[],"categories":["Apps and extensions for translation management","🤖 AI-Related Tools","Coding"],"sub_categories":["Jekyll","Other Cloud Provider Credits","Developer tools"],"readme":"# i18n Translate Action\n\nA GitHub Action that automatically translates i18n files using LLM providers (Anthropic Claude, OpenAI GPT, or Ollama).\n\n## Features\n\n- **Multiple LLM Providers**: Support for Anthropic Claude, OpenAI GPT, and local Ollama models\n- **Multiple Formats**: XLIFF 1.2, XLIFF 2.0, JSON (flat and nested)\n- **ICU Message Format**: Intelligent handling of plurals with CLDR rules for 20+ languages\n- **Change Detection**: Only translates new or modified strings using content hashing\n- **Rate Limiting**: Built-in rate limiting and retry logic for API calls\n- **Batch Processing**: Efficient batching of translation requests\n- **Git Integration**: Automatic commits of translated files\n\n## Quick Start\n\n```yaml\nname: Translate i18n files\n\non:\n  push:\n    branches: [main]\n    paths:\n      - 'locales/en/**'\n\njobs:\n  translate:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Translate\n        uses: your-org/i18n-translate-action@v1\n        with:\n          provider: anthropic\n          api-key: ${{ secrets.ANTHROPIC_API_KEY }}\n          source-language: en\n          target-languages: de,fr,es\n          files: 'locales/en/**/*.json'\n```\n\n## Inputs\n\n| Input | Description | Required | Default |\n|-------|-------------|----------|---------|\n| `provider` | LLM provider (`anthropic`, `openai`, `ollama`) | Yes | `anthropic` |\n| `api-key` | API key for the provider | No* | - |\n| `model` | Model to use | No | Provider default |\n| `source-language` | Source language code | Yes | `en` |\n| `target-languages` | Comma-separated target language codes | Yes | - |\n| `files` | Glob pattern for translation files | Yes | `**/*.xliff` |\n| `format` | File format (`xliff-1.2`, `xliff-2.0`, `json-flat`, `json-nested`, `auto`) | No | `auto` |\n| `config-file` | Path to configuration file | No | `.i18n-translate.yml` |\n| `commit` | Whether to commit changes | No | `true` |\n| `commit-message` | Commit message | No | `chore(i18n): update translations` |\n| `batch-size` | Strings per API call | No | `10` |\n| `max-retries` | Maximum retry attempts | No | `3` |\n| `ollama-url` | Ollama server URL | No | `http://localhost:11434` |\n| `dry-run` | Run without making changes | No | `false` |\n| `context` | Additional context for translations | No | - |\n\n*API key is required for Anthropic and OpenAI providers.\n\n## Outputs\n\n| Output | Description |\n|--------|-------------|\n| `translated-count` | Number of strings translated |\n| `files-updated` | Number of files updated |\n| `report` | Translation report in markdown |\n| `commit-sha` | SHA of the commit (if committed) |\n\n## Configuration File\n\nYou can use a `.i18n-translate.yml` file for configuration:\n\n```yaml\nprovider:\n  name: anthropic\n  model: claude-3-haiku-20240307\n  temperature: 0.3\n\ntranslation:\n  batchSize: 15\n  maxRetries: 3\n  context: \"Mobile app UI translations\"\n  preserveFormatting: true\n  preservePlaceholders: true\n\ngit:\n  enabled: true\n  commitMessage: \"chore(i18n): update translations\"\n\nfiles:\n  pattern: \"locales/**/*.json\"\n  format: json-nested\n  sourceLanguage: en\n  targetLanguages:\n    - de\n    - fr\n    - es\n    - ja\n  exclude:\n    - \"**/node_modules/**\"\n```\n\n## Supported File Formats\n\n### XLIFF 1.2\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cxliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\"\u003e\n  \u003cfile source-language=\"en\" target-language=\"de\"\u003e\n    \u003cbody\u003e\n      \u003ctrans-unit id=\"greeting\"\u003e\n        \u003csource\u003eHello, World!\u003c/source\u003e\n        \u003ctarget\u003e\u003c/target\u003e\n      \u003c/trans-unit\u003e\n    \u003c/body\u003e\n  \u003c/file\u003e\n\u003c/xliff\u003e\n```\n\n### XLIFF 2.0\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cxliff version=\"2.0\" srcLang=\"en\" trgLang=\"de\" xmlns=\"urn:oasis:names:tc:xliff:document:2.0\"\u003e\n  \u003cfile id=\"messages\"\u003e\n    \u003cunit id=\"greeting\"\u003e\n      \u003csegment\u003e\n        \u003csource\u003eHello, World!\u003c/source\u003e\n        \u003ctarget\u003e\u003c/target\u003e\n      \u003c/segment\u003e\n    \u003c/unit\u003e\n  \u003c/file\u003e\n\u003c/xliff\u003e\n```\n\n### JSON (Flat)\n\n```json\n{\n  \"greeting\": \"Hello, World!\",\n  \"button.save\": \"Save\"\n}\n```\n\n### JSON (Nested)\n\n```json\n{\n  \"greeting\": \"Hello, World!\",\n  \"button\": {\n    \"save\": \"Save\",\n    \"cancel\": \"Cancel\"\n  }\n}\n```\n\n## ICU Message Format Support\n\nThe action intelligently handles ICU MessageFormat patterns, including plurals:\n\n```json\n{\n  \"items_count\": \"{count, plural, one {# item} other {# items}}\"\n}\n```\n\nWhen translating to languages with different plural rules (like Russian, Arabic, or Polish), the action automatically generates the correct plural forms based on CLDR rules.\n\n### Supported Plural Rules\n\n- **Simple (one/other)**: English, German, Spanish, etc.\n- **Complex (one/few/many/other)**: Russian, Polish, Ukrainian, Czech\n- **Full (zero/one/two/few/many/other)**: Arabic\n- **None (other only)**: Japanese, Chinese, Korean\n\n## Provider Configuration\n\n### Anthropic Claude\n\n```yaml\n- uses: your-org/i18n-translate-action@v1\n  with:\n    provider: anthropic\n    api-key: ${{ secrets.ANTHROPIC_API_KEY }}\n    model: claude-3-haiku-20240307  # or claude-3-sonnet, claude-3-opus\n```\n\n### OpenAI GPT\n\n```yaml\n- uses: your-org/i18n-translate-action@v1\n  with:\n    provider: openai\n    api-key: ${{ secrets.OPENAI_API_KEY }}\n    model: gpt-4o-mini  # or gpt-4o, gpt-4-turbo\n```\n\n### Ollama (Self-hosted)\n\n```yaml\n- uses: your-org/i18n-translate-action@v1\n  with:\n    provider: ollama\n    model: llama3.2\n    ollama-url: http://localhost:11434\n```\n\n## Preventing Infinite Loops\n\nThe action automatically detects and skips runs triggered by its own commits. You can also use skip markers:\n\n```yaml\ncommit-message: \"chore(i18n): update translations [skip i18n]\"\n```\n\n## Development\n\n### Prerequisites\n\n- Node.js 20.x\n- npm\n\n### Setup\n\n```bash\nnpm install\n```\n\n### Build\n\n```bash\nnpm run build\n```\n\n### Test\n\n```bash\nnpm test\n```\n\n### Lint\n\n```bash\nnpm run lint\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi18n-actions%2Fai-i18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fi18n-actions%2Fai-i18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi18n-actions%2Fai-i18n/lists"}