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

@gringow/gringow

v0.2.0

Published

AI-powered translation library for template strings using multiple LLM providers

Downloads

392

Readme

@gringow/gringow

npm version License: MIT

AI-powered translation library for template strings using multiple LLM providers (Hugging Face, Anthropic, Gemini). Gringow provides smart caching, deterministic content hashing, and seamless integration for modern JavaScript/TypeScript projects.

Features

  • 🌍 Multi-language translation using LLM providers
  • 🏷️ Tagged template literal syntax for inline translations
  • 💾 Smart caching with content-based hashing
  • 🔌 Three LLM providers: Hugging Face (local), Anthropic, Gemini
  • 🚀 Zero configuration - works out of the box with Hugging Face
  • 📦 Optimized builds via Vite/Next.js plugins

Installation

npm install @gringow/gringow
# or
pnpm add @gringow/gringow
# or
yarn add @gringow/gringow

Quick Start

import Gringow from '@gringow/gringow'

// Simple string translation
const { cacheId, translation } = await Gringow`Hello world`
console.log(translation.translation)
// => { "pt-BR": "Olá mundo", "fr-CA": "Bonjour le monde" }

// Template string with dynamic values
const name = 'John'
const { translation: result } = await Gringow`Welcome, ${name}!`
console.log(result.translation)
// => { "pt-BR": "Bem-vindo, John!", "fr-CA": "Bienvenue, John!" }

Usage Examples

Basic Translation

import Gringow from '@gringow/gringow'

// Translate a static string
const { translation } = await Gringow`Hello world`
console.log(translation.translation['pt-BR']) // "Olá mundo"

Dynamic Content

// Template literals are flattened before hashing - dynamic values preserved
const user = { name: 'Alice', role: 'admin' }
const { translation } = await Gringow`User ${user.name} has ${user.role} privileges`

console.log(translation.translation['pt-BR'])
// => "Usuário Alice tem privilégios de admin"

Cache Management

import Gringow, { rebuild, checkCache } from '@gringow/gringow'

const { cacheId } = await Gringow`Hello world`

// Check if translation exists in cache
const cached = await checkCache(cacheId)
console.log(cached) // GringowCacheItem or undefined

// Force re-translation by rebuilding cache entry
const refreshed = await rebuild(cacheId)
console.log(refreshed.translation.translation)

Browser Usage

For client-side interpolation without Node.js dependencies:

import { interpolateTemplate } from '@gringow/gringow/browser'

const template = 'Hello {name}, you have {count} messages'
const result = interpolateTemplate(template, { name: 'Alice', count: 5 })
console.log(result) // "Hello Alice, you have 5 messages"

Configuration

Gringow uses cosmiconfig to load configuration from your project root. Supported formats: gringow.config.js, gringow.config.mjs, gringow.config.json, or a gringow field in package.json.

Default Configuration

// gringow.config.js
export default {
  debug: false,
  log: { level: 'info' },
  cache: {
    dir: './gringow',
    file: 'gringow.json',
    prefix: 'grw',
    write: true,
  },
  keys: {
    anthropicApiKey: process.env.ANTHROPIC_API_KEY,
    geminiApiKey: process.env.GEMINI_API_KEY,
  },
  sourceLanguage: 'en-US',
  languages: ['pt-BR', 'fr-CA'],
  llm: {
    choice: 'huggingface', // 'huggingface' | 'anthropic' | 'gemini'
    model: 'Xenova/nllb-200-distilled-600M',
    temperature: 1.0,
    sleep: 0,
  },
  globby: './src/**/*.{js,jsx,ts,tsx}',
}

Example: Using Gemini

// gringow.config.js
export default {
  keys: {
    geminiApiKey: process.env.GEMINI_API_KEY,
  },
  llm: {
    choice: 'gemini',
    model: 'gemini-2.0-flash',
    prePromptAppend: 'Please respond in a friendly tone.',
  },
  languages: ['es-ES', 'de-DE', 'ja-JP'],
}

Example: Using Anthropic

// gringow.config.js
export default {
  keys: {
    anthropicApiKey: process.env.ANTHROPIC_API_KEY,
  },
  llm: {
    choice: 'anthropic',
    model: 'claude-3-5-sonnet-20241022',
    temperature: 0.7,
  },
}

Prompt Customization

Fine-tune LLM behavior with prompt options:

export default {
  llm: {
    choice: 'huggingface',
    prePrompt: 'Translate the following text:', // Default prompt prefix
    postPrompt: 'Ensure translations are natural.', // Additional context
    prePromptAppend: 'Use formal language.', // Appended to pre-prompt
    postPromptPrepend: 'Maintain original formatting.', // Prepended to post-prompt
    prePromptReplace: 'Custom instruction here', // Replaces entire pre-prompt
  },
}

LLM Providers

Hugging Face (Default)

Runs local models via @huggingface/transformers. No API key required.

// gringow.config.js
export default {
  llm: {
    choice: 'huggingface',
    model: 'Xenova/nllb-200-distilled-600M', // Multilingual translation model
  },
}

Pros: Free, private, offline-capable
Cons: Slower first run (model download), higher memory usage

Anthropic

Uses Claude models via Anthropic API. Requires API key.

// gringow.config.js
export default {
  keys: {
    anthropicApiKey: process.env.ANTHROPIC_API_KEY,
  },
  llm: {
    choice: 'anthropic',
    model: 'claude-3-5-sonnet-20241022',
  },
}

Pros: High-quality translations, fast
Cons: API costs, requires internet

Gemini

Uses Google's Gemini models. Requires API key.

// gringow.config.js
export default {
  keys: {
    geminiApiKey: process.env.GEMINI_API_KEY,
  },
  llm: {
    choice: 'gemini',
    model: 'gemini-2.0-flash',
  },
}

Pros: Fast, cost-effective
Cons: API costs, requires internet

API Reference

Core Functions

Gringow(strings, ...values): Promise<GringowResponse>

Main translation function. Accepts tagged template literals or plain strings.

const result = await Gringow`Hello ${name}`

Returns: Promise<GringowResponse> with { cacheId, translation }

rebuild(cacheId: string): Promise<GringowResponse>

Re-translates a cached entry using the current LLM configuration.

const refreshed = await rebuild('grw_abc123')

Cache Helpers

import {
  checkCache,      // Check if cacheId exists
  getCache,        // Get entire cache object
  getOrCreateCache,// Get cache or create empty one
  writeCacheToDisk,// Manually write cache entry
  deleteCacheItem, // Remove cache entry
  clearCache,      // Clear all cache entries
} from '@gringow/gringow'

Utilities

import {
  createCacheId,         // Generate cache ID from string
  flatTemplateString,    // Flatten template literal to string
  interpolateTemplate,   // Browser-safe interpolation (from /browser export)
  awaitedConfig,         // Access resolved configuration
  isLocalConfigFound,    // Check if local config exists
  getConfigSource,       // Get config file path
} from '@gringow/gringow'

Type Definitions

type GringowTranslation = Record<string, string>

type GringowCacheItem = {
  original: string
  translation: GringowTranslation
  append?: string
  prepend?: string
  rebuild?: boolean
}

type GringowResponse = {
  cacheId: string
  translation: GringowCacheItem
}

How It Works

  1. Input Processing: Template strings are flattened to plain text (preserving dynamic values)
  2. Cache ID Generation: Content-based hash created using createCacheId()
  3. Cache Lookup: Check ./gringow/gringow.json for existing translation
  4. LLM Query: If not cached, request translation from configured provider
  5. Response Parsing: Parse provider response to GringowCacheItem format
  6. Cache Storage: Write to disk when cache.write is true

Example cache structure:

{
  "grw_a1b2c3": {
    "original": "Hello world",
    "translation": {
      "pt-BR": "Olá mundo",
      "fr-CA": "Bonjour le monde"
    }
  }
}

Development

# Install dependencies
pnpm install

# Build the package
pnpm run build

# Run tests
pnpm run test

# Watch mode
pnpm run test:watch

Integrations

Gringow has official integrations for modern web frameworks:

Related Resources

License

MIT © Renato Gaspar


Questions or Issues? Open an issue on GitHub