Core Library
@shipi18n/core is the engine every other package is built on. Use it directly when you want translation inside your own script or build step.
Install
npm install @shipi18n/core @anthropic-ai/sdk # or npm install @shipi18n/core openai
translateJSON
import { translateJSON } from '@shipi18n/core'
const { result, stats } = await translateJSON({
content: { greeting: 'Hello {{name}}' },
from: 'en',
to: 'es',
provider: 'anthropic', // 'anthropic' | 'openai' | custom adapter
apiKey: process.env.ANTHROPIC_API_KEY, // optional — falls back to the env var
})
console.log(result) // { greeting: 'Hola {{name}}' }
console.log(stats) // { translated, reused, placeholderWarnings }Options
| Option | Description |
|---|---|
content | The object to translate. Nested objects and arrays are walked; non-string leaves pass through untouched. |
from / to | Language codes. to takes a single language per call. |
provider | Provider name or a custom { complete } adapter. |
apiKey | Optional; the provider environment variable is used when omitted. |
model | Optional model override. |
existing | Previous translations. Keys already present are reused instead of re-translated. |
Incremental translation
const { result, stats } = await translateJSON({
content: source,
from: 'en',
to: 'fr',
provider: 'anthropic',
existing: previousFrench, // only new or empty keys are sent to the model
})
console.log(`translated ${stats.translated}, reused ${stats.reused}`)Checking placeholders yourself
import { validatePlaceholders } from '@shipi18n/core'
// Returns { ok, missing, added } — not an array. Check .ok, because a bare
// truthiness test on the result would always pass and silently protect nothing.
const { ok, missing, added } = validatePlaceholders(sourceString, translatedString)
if (!ok) {
throw new Error(
`placeholder drift: missing ${missing.join(', ') || 'none'}, ` +
`unexpected ${added.join(', ') || 'none'}`
)
}translateJSON already reports drift through stats.placeholderWarnings, so you rarely need to call this yourself. Each entry is { path, source, translation, ok, missing, added } — note path, not key. Failing your build on a non-empty array is a cheap safety net.
Module format
The package is ESM. Use "type": "module", an .mjs file, or a dynamic import() from CommonJS.