@molecule/api-ai-translation
Core interface · ai-translation · API (Node) · v1.1.0 · Apache-2.0
AI text-translation core interface — translate content between languages with detection, batching, and usage quotas via swappable providers.
npm install @molecule/api-ai-translationHow it works
@molecule/api-ai-translation is the ai-translation core interface on the API (Node) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 6 providers: @molecule/api-ai-translation-bergamot, @molecule/api-ai-translation-deepl, @molecule/api-ai-translation-google, @molecule/api-ai-translation-llm, @molecule/api-ai-translation-madlad, @molecule/api-ai-translation-molecule.
import { setProvider, requireProvider } from '@molecule/api-ai-translation'
import { createProvider } from '@molecule/api-ai-translation-deepl'
// Wire at startup. See the bond package for its config/env (e.g. DEEPL_API_KEY).
setProvider(createProvider())
// Use anywhere after startup.
const { translations } = await requireProvider().translate({
text: ['Hello world', 'Thanks for your order'],
targetLang: 'DE',
})
console.log(translations[0].text, translations[0].detectedSourceLang) // 'Hallo Welt', 'EN'Providers (6): @molecule/api-ai-translation-bergamot, @molecule/api-ai-translation-deepl, @molecule/api-ai-translation-google, @molecule/api-ai-translation-llm, @molecule/api-ai-translation-madlad, @molecule/api-ai-translation-molecule
Works with: @molecule/api-bond
Reference
AI text-translation core interface for molecule.dev.
Defines the AITranslationProvider contract — translate text between
languages (translate), list supported languages, and read billing-period
usage — plus the accessor (setProvider/getProvider/hasProvider/
requireProvider). Interface-only: bond a provider package (e.g.
@molecule/api-ai-translation-deepl).
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { setProvider, requireProvider } from '@molecule/api-ai-translation'
import { createProvider } from '@molecule/api-ai-translation-deepl'
// Wire at startup. See the bond package for its config/env (e.g. DEEPL_API_KEY).
setProvider(createProvider())
// Use anywhere after startup.
const { translations } = await requireProvider().translate({
text: ['Hello world', 'Thanks for your order'],
targetLang: 'DE',
})
console.log(translations[0].text, translations[0].detectedSourceLang) // 'Hallo Welt', 'EN'
Type
core
Installation
npm install @molecule/api-ai-translation @molecule/api-bond
API
Interfaces
TranslateParams
Parameters for translating text.
interface TranslateParams {
/** Text or array of texts to translate. Maximum 50 texts per request. */
text: string | string[]
/** Target language code (e.g., 'DE', 'FR', 'ES', 'EN-US'). */
targetLang: string
/** Source language code. If omitted, the provider auto-detects the language. */
sourceLang?: string
/** Formality preference. Not all providers or target languages support this. */
formality?: 'default' | 'more' | 'less' | 'prefer_more' | 'prefer_less'
/** Whether to preserve original formatting conventions. */
preserveFormatting?: boolean
/** Glossary identifier for consistent terminology. May require sourceLang to be set. */
glossaryId?: string
/** How to handle markup tags in the text ('xml' or 'html'). */
tagHandling?: 'xml' | 'html'
/** Additional context to improve translation accuracy (not translated itself). */
context?: string
/** Model type preference for quality vs latency trade-off. */
modelType?: 'quality_optimized' | 'prefer_quality_optimized' | 'latency_optimized'
/**
* Literal substrings that must come back exactly as sent — interpolation
* placeholders (`{{count}}`), code, product names. Every bond keeps them out of
* the translator's reach with its own mechanism and restores them afterwards;
* callers never mask anything themselves. The translator may still move them
* within the sentence (word order differs between languages).
*/
protect?: string[]
}
TranslatedText
A single translated text with its detected source language.
interface TranslatedText {
/** The translated text. */
text: string
/** Detected source language code (e.g., 'EN', 'DE'). */
detectedSourceLang: string
}
TranslationResult
Result of a translation request containing one or more translated texts.
interface TranslationResult {
/** Array of translation results, one per input text. */
translations: TranslatedText[]
}
SupportedLanguage
A language supported by the translation provider.
interface SupportedLanguage {
/** Language code (e.g., 'EN', 'DE', 'FR', 'PT-BR'). */
language: string
/** Human-readable language name (e.g., 'English', 'German'). */
name: string
/** Whether formality options are supported for this language. */
supportsFormality?: boolean
}
TranslationUsage
API usage statistics for the current billing period.
interface TranslationUsage {
/** Number of characters translated in the current billing period. */
characterCount: number
/** Maximum character limit for the current billing period. */
characterLimit: number
}
AITranslationProvider
AITranslation provider interface.
Bond packages implement this interface to provide translation services from different backends (DeepL, Google Translate, etc.).
interface AITranslationProvider {
/** Provider identifier (e.g., 'deepl', 'google'). */
readonly name: string
/**
* Translate one or more texts to a target language.
*
* @param params - Translation parameters including text(s) and target language.
* @returns Translation results with detected source languages.
*/
translate(params: TranslateParams): Promise<TranslationResult>
/**
* Get the list of languages supported by this provider.
*
* @param type - Whether to list 'source' or 'target' languages. Defaults to 'source'.
* @returns Array of supported languages with metadata.
*/
getSupportedLanguages(type?: 'source' | 'target'): Promise<SupportedLanguage[]>
/**
* Get current API usage statistics for the billing period.
*
* @returns Character count and limit for the current period.
*/
getUsage(): Promise<TranslationUsage>
}
AITranslationConfig
Base configuration for AITranslation providers.
interface AITranslationConfig {
/** API key for authentication. Typically falls back to an environment variable. */
apiKey?: string
/** Base URL for the translation API. */
baseUrl?: string
}
Functions
setProvider(provider)
Registers the AI translation provider singleton.
function setProvider(provider: AITranslationProvider): void
provider— The AI translation provider implementation to register.
getProvider()
Returns the bonded AI translation provider, or null if none is registered.
function getProvider(): AITranslationProvider | null
Returns: The active provider, or null.
hasProvider()
Returns whether an AI translation provider has been registered.
function hasProvider(): boolean
Returns: true if a provider is bonded.
requireProvider()
Returns the bonded AI translation provider, throwing if none is configured.
function requireProvider(): AITranslationProvider
Returns: The active provider.
Available Providers
| Provider | Package |
|---|---|
| Bergamot (self-hosted) | @molecule/api-ai-translation-bergamot |
| DeepL | @molecule/api-ai-translation-deepl |
| Google Translate | @molecule/api-ai-translation-google |
| LLM (any api-ai model) | @molecule/api-ai-translation-llm |
| MADLAD-400 | @molecule/api-ai-translation-madlad |
| Molecule (hosted) | @molecule/api-ai-translation-molecule |
Injection Notes
Requirements
Peer dependencies:
@molecule/api-bond^1.0.1
Runtime Dependencies
-
@molecule/api-bond -
Wire it at startup with
setProvider(...)— or the equivalentbond('ai-translation', provider). This core routes through the shared@molecule/api-bondregistry, so either call registers the same provider andvalidateBonds()reports it as missing when unwired. -
This translates CONTENT, not the UI. App chrome/labels stay on the i18n system (
t(key, values, { defaultValue })+ locale bonds); use this bond for user-generated or dynamic text. -
Language codes are provider-flavored and regional variants matter on the target side (e.g. 'EN-US' vs 'EN', 'PT-BR') — don't hardcode a guessed list; populate pickers from
getSupportedLanguages('target')and pass codes through verbatim. -
translateis batched: passtext: string[](max 50 per request) instead of looping; results return oneTranslatedTextper input, each withdetectedSourceLangwhensourceLangwas omitted. -
Server-side only + quota-aware. Keep the provider key on the API; translation is billed per character (
getUsage()exposes the period quota) — auth and rate-limit any endpoint that translates caller-supplied text. -
formalityand glossaries are provider/language-dependent — treat them as best-effort hints, not guarantees. -
Placeholders: pass them in
protect, never mask them yourself. Machine translators rewrite{{count}}into{{Anzahl}}or split its braces; each bond knows its service's "do not translate" mechanism (DeepLignore_tags, Googletranslate="no", …) and restores the originals. Still check the result holds every placeholder before storing it — a translator can drop one. -
Output is plain text unless you set
tagHandling. Bonds that use markup internally escape&/</>on the way in and decode entities on the way out. -
Failed requests throw an
Errorcarrying the HTTPstatuswhen the service returned one (e.g. DeepL 456 = quota exhausted), so callers can fall back.
E2E Tests
Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip. The sandbox has a live AI provider, so translations run for real; output is non-deterministic, so assert on the resulting LANGUAGE/meaning, never an exact string:
- Translating real text to a target language through the UI returns text ACTUALLY in that language — English→Spanish produces recognizably Spanish, not the original echoed back or left in English.
- Switching the target language (from the picker populated by getSupportedLanguages('target')) changes the output language for the same input — the same source re-translates into the newly chosen language.
- With sourceLang omitted the provider auto-detects: a known-language input comes back with the correct detectedSourceLang, and if the UI shows a detected-language label it names the right one.
- Text already in the target language is left sensible — unchanged or a valid paraphrase, never mangled, doubled, or emptied.
- Empty or untranslatable input (whitespace, emoji, a bare code snippet) is handled gracefully — a clear UI state, nothing crashes.
- A provider failure (bad key, quota exhausted, network drop) surfaces a visible error in the UI, not an unhandled 500 or a silently blank result.
- The translate call runs server-side only — the provider key never reaches the browser (check the network panel: no key in any request).