---
title: "Translation"
canonical: https://docs.qvac.tether.io/sdk/v0.18/ai-capabilities/translation/
collection: "SDK"
package: "@qvac/sdk"
line: v0.18
current_line: false
---

# Translation (/sdk/v0.18/ai-capabilities/translation)



## Overview

Translation uses your choice of either [`qvac-fabric-llm.cpp`](https://github.com/tetherto/qvac-fabric-llm.cpp) or [Bergamot](https://browser.mt) as inference engine. Load any supported model using `modelType: "nmt"`, and `modelConfig.engine: "Bergamot"` for Bergamot.

Translation input is defined by:

* `from: string`: source language id (e.g., "en")
* `to: string`: target language id
* `text: string | string[]`: text to be translated

`translate()` returns an object containing `translations` — one entry per input, in the order the inputs were given — and `text`, those entries joined by newlines. When streaming is enabled it returns a `tokenStream` for real-time output instead; a batch emits one whole translation per token, so the position of each token is the position of its input.

For a list of supported languages and their ids (string abbreviations), see [qvac-sdk/schemas/translation-config.ts](https://github.com/tetherto/qvac/blob/main/packages/sdk/schemas/translation-config.ts).

## Functions

Use the following sequence of function calls:

1. [`loadModel()`](/sdk/v0.18/reference/api#loadmodel)
2. [`translate()`](/sdk/v0.18/reference/api#translate)
3. [`unloadModel()`](/sdk/v0.18/reference/api#unloadmodel)

For how to use each function, see [SDK — API reference](/sdk/v0.18/reference/api/).

## Models

You should load a model compatible with your chosen inference engine:

* `qvac-fabric-llm.cpp` (default): Bergamot or IndicTrans2. Bergamot uses intgemm `*.bin` + `*.spm` vocab files; IndicTrans2 uses GGML `*.bin`.
* Bergamot: Bergamot model bundle. Required files: model `*.bin` + `vocab*.spm`.

For models available as constants, see [SDK — Models](/sdk/v0.18/#models).

## Example

The following script shows an example of translation:

<Tabs>
  <Tab value="js" label="JavaScript" default>
    <WrapCode>
      ```js file=<rootDir>/packages/sdk/dist/examples/translation/translation-stream.js title="translation.js" lineNumbers
      import { loadModel, translate, unloadModel, BERGAMOT_EN_ES } from '@qvac/sdk';
      try {
          const modelId = await loadModel({
              modelSrc: BERGAMOT_EN_ES,
              modelConfig: {
                  engine: 'Bergamot',
                  from: 'en',
                  to: 'es'
              }
          });
          console.log(`▸ Model loaded: ${modelId}`);
          const text = 'Hello, how are you today? I hope you are having a wonderful day!';
          console.log('▸ Streaming Translation');
          const streamResult = translate({
              modelId,
              text,
              modelType: 'nmtcpp-translation',
              stream: true
          });
          process.stdout.write('Translated text EN -> ES: ');
          for await (const token of streamResult.tokenStream) {
              process.stdout.write(token);
          }
          console.log();
          const stats = await streamResult.stats;
          if (stats) {
              console.log(`▸ Processing stats:`, stats);
          }
          await unloadModel({ modelId, clearStorage: false });
      }
      catch (error) {
          console.error('✖', error);
          process.exit(1);
      }
      ```
    </WrapCode>
  </Tab>

  <Tab value="ts" label="TypeScript">
    <WrapCode>
      ```ts file=<rootDir>/packages/sdk/examples/translation/translation-stream.ts title="translation.ts" lineNumbers
      import { loadModel, translate, unloadModel, BERGAMOT_EN_ES } from '@qvac/sdk'

      try {
        const modelId = await loadModel({
          modelSrc: BERGAMOT_EN_ES,
          modelConfig: {
            engine: 'Bergamot',
            from: 'en',
            to: 'es'
          }
        })

        console.log(`▸ Model loaded: ${modelId}`)

        const text = 'Hello, how are you today? I hope you are having a wonderful day!'

        console.log('▸ Streaming Translation')
        const streamResult = translate({
          modelId,
          text,
          modelType: 'nmtcpp-translation',
          stream: true
        })

        process.stdout.write('Translated text EN -> ES: ')
        for await (const token of streamResult.tokenStream) {
          process.stdout.write(token)
        }
        console.log()

        const stats = await streamResult.stats
        if (stats) {
          console.log(`▸ Processing stats:`, stats)
        }

        await unloadModel({ modelId, clearStorage: false })
      } catch (error) {
        console.error('✖', error)
        process.exit(1)
      }
      ```
    </WrapCode>
  </Tab>

  <Tab value="python" label="Python">
    <WrapCode>
      ```python file=<rootDir>/packages/sdk-python/examples/translation.py title="translation.py" lineNumbers
      """Python port of packages/sdk/examples/translation/translation-llm.ts.

      LLM-backed translation with an explicit source language and with source
      auto-detection. `translate()` returns a run whose `text` is an awaitable full
      string (non-stream mode); with `from_` omitted for an LLM model, the source
      language is detected from the input (needs the `langdetect` extra).

      RUN: python examples/translation.py
      """

      from __future__ import annotations

      import asyncio
      import sys

      from tetherto.qvac_sdk import Client, load_model, translate, unload_model
      from tetherto.qvac_sdk.models import SALAMANDRATA_2B_INST_Q4


      def print_progress(p) -> None:
          """Print model download progress; pass as `on_progress=` to `load_model`."""
          line = (
              f"▸ Downloading {p.percentage:.0f}% "
              f"({p.downloaded / 1e6:.1f}/{p.total / 1e6:.1f} MB)"
          )
          print(line, end="\r" if sys.stderr.isatty() else "\n", file=sys.stderr)
          if p.percentage >= 100:
              print(file=sys.stderr)


      async def main() -> int:
          async with Client() as client:
              t = client.transport
              try:
                  model_id = await load_model(
                      t, model_src=SALAMANDRATA_2B_INST_Q4, on_progress=print_progress
                  )

                  # Explicit source language.
                  eng_text = "Hello, how are you today?"
                  explicit = translate(
                      t,
                      model_id=model_id,
                      text=eng_text,
                      from_="en",
                      to="it",
                      model_type="llamacpp-completion",
                      stream=False,
                  )
                  translated_explicit = await explicit.text

                  # Auto-detected source (await the previous translate first — the LLM
                  # addon runs one job at a time).
                  esp_text = "Hola, como estas?"
                  autodetect = translate(
                      t,
                      model_id=model_id,
                      text=esp_text,
                      to="en",
                      model_type="llamacpp-completion",
                      stream=False,
                  )
                  translated_autodetect = await autodetect.text

                  print(f'Explicit source: {eng_text} -> "{translated_explicit}"')
                  print(f'Autodetected source: {esp_text} -> "{translated_autodetect}"')

                  await unload_model(t, model_id)
              except Exception as error:
                  print(f"✖ {error}", file=sys.stderr)
                  return 1
          return 0


      if __name__ == "__main__":
          sys.exit(asyncio.run(main()))
      ```
    </WrapCode>
  </Tab>
</Tabs>

<Callout type="success">
  **Tip:** all examples throughout this documentation are self-contained and runnable. For instructions on how to run them, see the [JS/TS quickstart](/sdk/v0.18/js-ts-sdk#quickstart) or the [Python quickstart](/sdk/v0.18/python-sdk#quickstart).
</Callout>
