npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

polyglot-i18n

v0.2.3

Published

AI-powered i18n translation CLI + GitHub Action. Translate JSON locale files using Gemini or DeepL.

Readme

polyglot-i18n

AI-powered i18n translation CLI + GitHub Action. Translate JSON locale files using Google Gemini or DeepL.

Drop-in replacement for locize, Crowdin, and Phrase — zero recurring SaaS cost.

Features

  • Two providers: Google Gemini (AI, cheap) and DeepL (professional quality)
  • Incremental: Only translates missing or changed keys — won't overwrite manual edits
  • Preserves: {{variables}}, nested JSON, plurals (_one/_other), HTML tags
  • Two modes: Namespaced directories (en/common.json) or flat files (en.json)
  • GitHub Action: Auto-creates a PR with translated files
  • Dry run: Preview what would be translated before running

Install

npm install -g polyglot-i18n

Quick Start

# Translate all English namespaces to 6 languages using Gemini
export GOOGLE_API_KEY="your-key"
polyglot-i18n translate -i ./locales/en -o sv,fr,de,it,es,zh

# Use DeepL instead
export DEEPL_API_KEY="your-key"
polyglot-i18n translate -i ./locales/en -o sv,fr,de -p deepl

# Translate a single flat file
polyglot-i18n translate -i ./en.json -o sv,fr,de

# Force retranslate everything
polyglot-i18n translate -i ./locales/en -o sv --force

# Dry run — see what would be translated
polyglot-i18n translate -i ./locales/en -o sv --dry-run

# Add domain context for better translations
polyglot-i18n translate -i ./locales/en -o sv -c "E-commerce checkout flow"

CLI Reference

polyglot-i18n translate [options]

Options:
  -i, --input <path>              Source English file or directory (required)
  -o, --output-languages <langs>  Comma-separated target language codes (required)
  -p, --provider <provider>       gemini or deepl (default: gemini)
  -m, --model <model>             Gemini model (default: gemini-3.1-flash-lite-preview)
  -k, --api-key <key>             API key (or use GOOGLE_API_KEY / DEEPL_API_KEY env)
  --output-dir <path>             Output directory
  -f, --force                     Retranslate all keys
  --dry-run                       Preview without translating
  --cache-file <path>             Cache file path (default: .polyglot-cache.json)
  --no-cache                      Disable incremental cache
  -c, --context <text>            Domain context for better translations

GitHub Action

name: Translate
on:
  workflow_dispatch:
    inputs:
      force:
        description: 'Force retranslate all keys'
        required: false
        default: false
        type: boolean

permissions:
  contents: write
  pull-requests: write

jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: CellarNode/polyglot-i18n@v1
        with:
          input: './locales/en'
          output-languages: 'sv,fr,de,it,es,zh'
          api-key: ${{ secrets.GOOGLE_API_KEY }}
          context: 'Your app description'
          force: ${{ inputs.force }}

The action automatically creates a PR with the translated files.

Action Inputs

| Input | Required | Default | Description | |-------|----------|---------|-------------| | provider | No | gemini | gemini or deepl | | input | Yes | — | Path to English source file/directory | | output-languages | Yes | — | Comma-separated target language codes | | api-key | Yes | — | Provider API key | | model | No | gemini-3.1-flash-lite-preview | Model (Gemini only) | | output-dir | No | auto | Output directory | | force | No | false | Retranslate all keys | | context | No | — | Domain context |

How Incremental Translation Works

polyglot-i18n tracks which English strings have been translated via a .polyglot-cache.json file:

| Key state | What happens | |-----------|-------------| | Missing — key in English but not in target | Translated | | Changed — English value changed since last run | Retranslated | | Unchanged — same as last run | Skipped (existing translation preserved) |

Use --force to retranslate everything regardless of cache state.

Providers

Google Gemini

Default provider. Set GOOGLE_API_KEY env var or pass --api-key.

Default model: gemini-3.1-flash-lite-preview. Override with --model.

DeepL

Set DEEPL_API_KEY env var or pass --api-key. Free and Pro tiers auto-detected from the key format (free keys end in :fx).

polyglot-i18n translate -i ./locales/en -o sv,fr,de -p deepl

Supported Input Formats

Namespaced directory:

locales/en/common.json    →    locales/sv/common.json
locales/en/auth.json      →    locales/sv/auth.json

Flat file:

en.json    →    sv.json, fr.json, de.json

Auto-detected from the input path.

Programmatic API

import { translate, GeminiProvider } from "polyglot-i18n";

const provider = new GeminiProvider(process.env.GOOGLE_API_KEY!);

const result = await translate({
  input: "./locales/en",
  outputLanguages: ["sv", "fr", "de"],
  provider,
  context: "E-commerce platform",
});

console.log(`Translated ${result.translated} keys, skipped ${result.skipped}`);

License

MIT