New:Microsoft Teams Notifications Are Now Available in Socket.Learn more →
Get Started

@shipi18n/api

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shipi18n/api

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

latest
Source
npmnpm
Version
1.1.0
Version published
Maintainers
1
Created
Source

@shipi18n/api

npm version npm downloads License: Apache 2.0 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 (*, **)
  contextAnnotations: {            // Context hints for ambiguous words
    'close': 'button - dismiss window',
    'address': 'form field - location',
  },
});

HTML Handling Modes:

ModeDescription
noneLeave HTML as-is (default)
stripRemove all HTML tags
decodeDecode HTML entities (& → &)
preserveKeep 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:

ScenarioBehavior
Missing translation for languageFalls back to regional variant (pt-BR → pt), then source
Missing translation for keyFills key from source content
API errorReturns 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:

PatternMatches
states.CAExact path only
states.*states.CA, states.NY (single level)
config.*.secretconfig.api.secret, config.db.secret
**.internalAny path ending with .internal

Context Annotations

Improve translation quality for ambiguous words by providing context hints:

const result = await shipi18n.translateJSON({
  content: {
    close: 'Close',
    address: 'Address',
    greeting: 'Hello',
  },
  sourceLanguage: 'en',
  targetLanguages: ['es'],
  contextAnnotations: {
    'close': 'button - dismiss window',      // Not "nearby"
    'address': 'form field - physical location', // Not "to address someone"
  },
});

// Result: "close" → "Cerrar" (not "Cerca")
// Result: "address" → "Dirección" (not "Dirigirse")

// Check which keys used context:
if (result.contextEnhanced) {
  console.log(`${result.contextEnhanced.count} keys used context annotations`);
  console.log(result.contextEnhanced.keys); // ['close', 'address']
}

The API automatically warns when translating keys that may contain legal content:

const result = await shipi18n.translateJSON({
  content: {
    terms_of_service: 'Terms of Service',
    privacy_policy: 'Privacy Policy',
    greeting: 'Hello',
  },
  sourceLanguage: 'en',
  targetLanguages: ['es'],
});

// Check for legal content warnings:
const legalWarning = result.warnings?.find(w => w.type === 'legal_content');
if (legalWarning) {
  console.warn(legalWarning.message);
  // "⚠️ Legal content detected (2 keys). Machine-translated legal text may not be legally binding."
  console.log(legalWarning.details.keys); // ['terms_of_service', 'privacy_policy']
}

Detected patterns: terms, privacy, disclaimer, legal, tos, eula, copyright, license, gdpr, cookie_policy, compliance, data_protection, refund, warranty

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

CodeDescription
MISSING_API_KEYAPI key not provided
INVALID_API_KEYAPI key is invalid
QUOTA_EXCEEDEDMonthly character limit reached
RATE_LIMITEDToo many requests
TIMEOUTRequest timed out
NETWORK_ERRORNetwork connection failed

Supported Languages

Over 100 languages supported. Common codes:

CodeLanguage
enEnglish
esSpanish
frFrench
deGerman
itItalian
ptPortuguese
zhChinese
jaJapanese
koKorean
arArabic
ruRussian
hiHindi

Get Your API Key

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

Documentation & Resources

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

ResourceLink
Getting Startedshipi18n.com
API Referenceshipi18n.com/api
i18next Best Practicesshipi18n.com/integrations/react
Blog & Tutorialsshipi18n.com/blog
PackageDescription
@shipi18n/cliCLI tool for translating files
vite-plugin-shipi18nVite plugin for build-time translation
i18next-shipi18n-backendi18next backend for dynamic loading
shipi18n-github-actionGitHub Action for CI/CD

Examples

License

Licensed under the Apache License, Version 2.0. See LICENSE.

shipi18n.com · GitHub · Pricing

Keywords

i18n

FAQs

Package last updated on 23 Jul 2026

Related posts