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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@shipi18n/api

v1.0.6

Published

Official Shipi18n API client for Node.js - translate JSON, text, and i18n files

Readme

@shipi18n/api

npm version npm downloads License: MIT GitHub last commit CI codecov

Official Node.js client for the Shipi18n translation API. Translate JSON, text, and i18n files with a simple, type-safe API.

Why Shipi18n?

  • Stop copy-pasting into Google Translate - One API call translates to 100+ languages
  • Placeholders stay intact - {name}, {{count}}, %s are preserved automatically
  • i18next-native - Built-in pluralization, namespaces, ICU MessageFormat support
  • 90-day Translation Memory - Same content? Cached. No extra cost.
  • Key-based pricing - Pay for unique strings, not characters or API calls

Installation

npm install @shipi18n/api

Quick Start

import { Shipi18n } from '@shipi18n/api';

const shipi18n = new Shipi18n({
  apiKey: 'your-api-key', // Get your API key at https://shipi18n.com
});

// Translate JSON
const result = await shipi18n.translateJSON({
  content: {
    greeting: 'Hello',
    farewell: 'Goodbye',
  },
  sourceLanguage: 'en',
  targetLanguages: ['es', 'fr', 'de'],
});

console.log(result.es); // { greeting: 'Hola', farewell: 'Adiós' }
console.log(result.fr); // { greeting: 'Bonjour', farewell: 'Au revoir' }
console.log(result.de); // { greeting: 'Hallo', farewell: 'Auf Wiedersehen' }

Features

  • JSON Translation - Translate nested JSON objects while preserving structure
  • Placeholder Preservation - Keeps {name}, {{count}}, %s placeholders intact
  • i18next Support - Full support for pluralization, namespaces, and ICU MessageFormat
  • TypeScript - Full type definitions included
  • Zero Dependencies - Uses native fetch (Node.js 18+)

API Reference

Constructor

const shipi18n = new Shipi18n({
  apiKey: 'your-api-key',     // Required
  baseUrl: 'https://ydjkwckq3f.execute-api.us-east-1.amazonaws.com', // Optional, default shown
  timeout: 30000,             // Optional, request timeout in ms
});

translateJSON(options)

Translate JSON content to multiple languages.

const result = await shipi18n.translateJSON({
  content: { greeting: 'Hello' },  // Object or JSON string
  sourceLanguage: 'en',
  targetLanguages: ['es', 'fr'],
  preservePlaceholders: true,      // Default: true
  enablePluralization: true,       // Default: true (i18next-style)
  htmlHandling: 'none',            // 'none' | 'strip' | 'decode' | 'preserve'
  namespace: 'common',             // Optional: wrap output in namespace
  groupByNamespace: 'auto',        // 'auto' | 'true' | 'false'
  exportPerNamespace: false,       // Split output by namespace
  skipKeys: ['brandName'],         // Skip exact key paths from translation
  skipPaths: ['states.*'],         // Skip using glob patterns (*, **)
});

HTML Handling Modes: | Mode | Description | |------|-------------| | none | Leave HTML as-is (default) | | strip | Remove all HTML tags | | decode | Decode HTML entities (&&) | | preserve | Keep HTML tags and translate text between them |

translateText(options)

Translate plain text to multiple languages.

const result = await shipi18n.translateText({
  content: 'Hello, world!',        // String or string[]
  sourceLanguage: 'en',
  targetLanguages: ['es', 'fr'],
  preservePlaceholders: true,
  htmlHandling: 'none',            // 'none' | 'strip' | 'decode' | 'preserve'
});

// result.es = [{ original: 'Hello, world!', translated: '¡Hola, mundo!' }]

translateI18next(options)

Convenience method for i18next files with all features enabled.

const result = await shipi18n.translateI18next({
  content: {
    common: {
      greeting: 'Hello, {{name}}!',
      items_one: '{{count}} item',
      items_other: '{{count}} items',
    },
  },
  sourceLanguage: 'en',
  targetLanguages: ['es', 'fr', 'de'],
});

Fallback Options

Handle missing translations gracefully with built-in fallback support:

const result = await shipi18n.translateJSON({
  content: { greeting: 'Hello', farewell: 'Goodbye' },
  sourceLanguage: 'en',
  targetLanguages: ['es', 'pt-BR', 'zh-TW'],
  fallback: {
    fallbackToSource: true,    // Use source content when translation missing (default: true)
    regionalFallback: true,    // pt-BR → pt, zh-TW → zh fallback (default: true)
    fallbackLanguage: 'en',    // Custom fallback language (optional)
  },
});

// If pt-BR translation fails, uses pt translation
// If pt also fails, uses English source content

// Check what fallbacks were used:
if (result.fallbackInfo?.used) {
  console.log(result.fallbackInfo.regionalFallbacks);      // { 'pt-BR': 'pt' }
  console.log(result.fallbackInfo.languagesFallbackToSource); // ['zh-TW']
  console.log(result.fallbackInfo.keysFallback);           // { es: ['farewell'] }
}

Fallback behavior: | Scenario | Behavior | |----------|----------| | Missing translation for language | Falls back to regional variant (pt-BR → pt), then source | | Missing translation for key | Fills key from source content | | API error | Returns source content for all languages (if enabled) |

Skipping Keys

Exclude specific keys or patterns from translation - useful for brand names, US state codes, or config values that should remain untranslated:

const result = await shipi18n.translateJSON({
  content: {
    greeting: 'Hello',
    brandName: 'Acme Inc',           // Should stay as-is
    states: { CA: 'California', NY: 'New York' }, // State names
    config: { api: { secret: 'xyz' } },
  },
  sourceLanguage: 'en',
  targetLanguages: ['es', 'fr'],
  skipKeys: ['brandName', 'config.api.secret'],  // Exact paths
  skipPaths: ['states.*'],                        // Glob patterns
});

// Skipped keys are preserved in original language
// result.es.brandName === 'Acme Inc'
// result.es.states.CA === 'California'

// Check what was skipped:
if (result.skipped) {
  console.log(`Skipped ${result.skipped.count} keys:`, result.skipped.keys);
}

Pattern Matching: | Pattern | Matches | |---------|---------| | states.CA | Exact path only | | states.* | states.CA, states.NY (single level) | | config.*.secret | config.api.secret, config.db.secret | | **.internal | Any path ending with .internal |

Examples

Nested JSON with Namespaces

const result = await shipi18n.translateJSON({
  content: {
    common: {
      buttons: {
        submit: 'Submit',
        cancel: 'Cancel',
      },
    },
    checkout: {
      total: 'Total: {{amount}}',
      pay: 'Pay Now',
    },
  },
  sourceLanguage: 'en',
  targetLanguages: ['es'],
});

// Namespaces are auto-detected and preserved
console.log(result.es);
// {
//   common: { buttons: { submit: 'Enviar', cancel: 'Cancelar' } },
//   checkout: { total: 'Total: {{amount}}', pay: 'Pagar ahora' }
// }

Pluralization (i18next-style)

const result = await shipi18n.translateJSON({
  content: {
    items_one: '{{count}} item',
    items_other: '{{count}} items',
  },
  sourceLanguage: 'en',
  targetLanguages: ['ru'], // Russian has more plural forms
});

// Automatically generates correct plural forms for each language
console.log(result.ru);
// {
//   items_one: '{{count}} элемент',
//   items_few: '{{count}} элемента',
//   items_many: '{{count}} элементов',
//   items_other: '{{count}} элементов'
// }

ICU MessageFormat

const result = await shipi18n.translateJSON({
  content: {
    welcome: '{gender, select, male {Welcome, Mr. {name}} female {Welcome, Ms. {name}} other {Welcome, {name}}}',
  },
  sourceLanguage: 'en',
  targetLanguages: ['es'],
});

// ICU syntax is preserved, only translatable text is translated

Export Per Namespace (for separate files)

const result = await shipi18n.translateJSON({
  content: {
    common: { greeting: 'Hello' },
    checkout: { pay: 'Pay' },
  },
  sourceLanguage: 'en',
  targetLanguages: ['es', 'fr'],
  exportPerNamespace: true,
});

// result.namespaceFiles contains pre-split translations:
// {
//   common: { es: { greeting: 'Hola' }, fr: { greeting: 'Bonjour' } },
//   checkout: { es: { pay: 'Pagar' }, fr: { pay: 'Payer' } }
// }

// result.namespaceFileNames suggests file names:
// [
//   { namespace: 'common', files: ['common.es.json', 'common.fr.json'] },
//   { namespace: 'checkout', files: ['checkout.es.json', 'checkout.fr.json'] }
// ]

Error Handling

import { Shipi18n, Shipi18nError } from '@shipi18n/api';

try {
  const result = await shipi18n.translateJSON({ ... });
} catch (error) {
  if (error instanceof Shipi18nError) {
    console.error(`Error ${error.statusCode}: ${error.message}`);
    console.error(`Code: ${error.code}`);
  }
}

Error Codes

| Code | Description | |------|-------------| | MISSING_API_KEY | API key not provided | | INVALID_API_KEY | API key is invalid | | QUOTA_EXCEEDED | Monthly character limit reached | | RATE_LIMITED | Too many requests | | TIMEOUT | Request timed out | | NETWORK_ERROR | Network connection failed |

Supported Languages

Over 100 languages supported. Common codes:

| Code | Language | |------|----------| | en | English | | es | Spanish | | fr | French | | de | German | | it | Italian | | pt | Portuguese | | zh | Chinese | | ja | Japanese | | ko | Korean | | ar | Arabic | | ru | Russian | | hi | Hindi |

Get Your API Key

  1. Sign up at shipi18n.com
  2. Go to Dashboard > API Keys
  3. Generate a new API key

Documentation & Resources

📚 Full Documentation: shipi18n.com/integrations/nodejs-sdk

| Resource | Link | |----------|------| | Getting Started | shipi18n.com | | API Reference | shipi18n.com/api | | i18next Best Practices | shipi18n.com/integrations/react | | Blog & Tutorials | shipi18n.com/blog |

Related Packages

| Package | Description | |---------|-------------| | @shipi18n/cli | CLI tool for translating files | | vite-plugin-shipi18n | Vite plugin for build-time translation | | i18next-shipi18n-backend | i18next backend for dynamic loading | | shipi18n-github-action | GitHub Action for CI/CD |

Examples

License

MIT