Skip to content

The Browser That Speaks 200 Languages: Building an AI Translator Without APIs

Published: at 

Introduction

Most AI translation tools rely on external APIs. This means sending data to servers and paying for each request. But what if you could run translations directly in your browser? This guide shows you how to build a free, offline translator that handles 200 languages using Vue and Transformers.js.

The Tools

Text

Initialize

Load

Results

Stream

Translation

Vue Frontend

Web Worker

Transformers.js

NLLB-200 Model

Architecture Overview

Building the Translator

AI Translator

1. Set Up Your Project

Create a new Vue project with TypeScript:

npm create vite@latest vue-translator -- --template vue-ts
cd vue-translator
npm install
npm install @huggingface/transformers

2. Create the Translation Worker

The translation happens in a background process. Create src/worker/translation.worker.ts:

import { import pipelinepipeline, import TextStreamerTextStreamer, import TranslationPipelineTranslationPipeline } from '@huggingface/transformers';
import type { import PipelineTypePipelineType, import ProgressCallbackProgressCallback } from '@huggingface/transformers';

// Singleton pattern for the translation pipeline
class class MyTranslationPipelineMyTranslationPipeline {
  static MyTranslationPipeline.task: PipelineTypetask: import PipelineTypePipelineType = 'translation';
  // We use the distilled model for faster loading and inference
  static MyTranslationPipeline.model: stringmodel = 'Xenova/nllb-200-distilled-600M';
  static MyTranslationPipeline.instance: anyinstance: import TranslationPipelineTranslationPipeline | null = null;

  static async MyTranslationPipeline.getInstance(progress_callback?: ProgressCallback): Promise<any>getInstance(progress_callback: anyprogress_callback?: import ProgressCallbackProgressCallback) {
    if (!this.MyTranslationPipeline.instance: anyinstance) {
      this.MyTranslationPipeline.instance: anyinstance = await import pipelinepipeline(this.MyTranslationPipeline.task: PipelineTypetask, this.MyTranslationPipeline.model: stringmodel, { progress_callback: anyprogress_callback }) as import TranslationPipelineTranslationPipeline;
    }
    return this.MyTranslationPipeline.instance: anyinstance;
  }
}

// Type definitions for worker messages
interface TranslationRequest {
  TranslationRequest.text: stringtext: string;
  TranslationRequest.src_lang: stringsrc_lang: string;
  TranslationRequest.tgt_lang: stringtgt_lang: string;
}

// Worker message handler
var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
.addEventListener<"message">(type: "message", listener: (this: Window, ev: MessageEvent<any>) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)
addEventListener
('message', async (event: MessageEvent<TranslationRequest>event: interface MessageEvent<T = any>
A message received by a target object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent)
@sincev15.0.0
MessageEvent
<TranslationRequest>) => {
try { // Initialize the translation pipeline with progress tracking const const translator: anytranslator = await class MyTranslationPipelineMyTranslationPipeline.MyTranslationPipeline.getInstance(progress_callback?: ProgressCallback): Promise<any>getInstance(x: anyx => { var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
.function postMessage(message: any, options?: WindowPostMessageOptions): void (+1 overload)
Posts a message to the given window. Messages can be structured objects, e.g. nested objects and arrays, can contain JavaScript values (strings, numbers, Date objects, etc), and can contain certain data objects such as File Blob, FileList, and ArrayBuffer objects. Objects listed in the transfer member of options are transferred, not just cloned, meaning that they are no longer usable on the sending side. A target origin can be specified using the targetOrigin member of options. If not provided, it defaults to "/". This default restricts the message to same-origin targets only. If the origin of the target window doesn't match the given target origin, the message is discarded, to avoid information leakage. To send the message to the target regardless of origin, set the target origin to "*". Throws a "DataCloneError" DOMException if transfer array contains duplicate objects or if message could not be cloned. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/postMessage)
postMessage
(x: anyx);
}); // Configure streaming for real-time translation updates const const streamer: anystreamer = new import TextStreamerTextStreamer(const translator: anytranslator.tokenizer, { skip_prompt: booleanskip_prompt: true, skip_special_tokens: booleanskip_special_tokens: true, callback_function: (text: string) => voidcallback_function: (text: stringtext: string) => { var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
.function postMessage(message: any, options?: WindowPostMessageOptions): void (+1 overload)
Posts a message to the given window. Messages can be structured objects, e.g. nested objects and arrays, can contain JavaScript values (strings, numbers, Date objects, etc), and can contain certain data objects such as File Blob, FileList, and ArrayBuffer objects. Objects listed in the transfer member of options are transferred, not just cloned, meaning that they are no longer usable on the sending side. A target origin can be specified using the targetOrigin member of options. If not provided, it defaults to "/". This default restricts the message to same-origin targets only. If the origin of the target window doesn't match the given target origin, the message is discarded, to avoid information leakage. To send the message to the target regardless of origin, set the target origin to "*". Throws a "DataCloneError" DOMException if transfer array contains duplicate objects or if message could not be cloned. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/postMessage)
postMessage
({
status: stringstatus: 'update', output: stringoutput: text: stringtext }); } }); // Perform the translation const const output: anyoutput = await const translator: anytranslator(event: MessageEvent<TranslationRequest>event.MessageEvent<TranslationRequest>.data: TranslationRequest
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.TranslationRequest.text: stringtext, {
// @ts-ignore - Type definitions are incomplete tgt_lang: stringtgt_lang: event: MessageEvent<TranslationRequest>event.MessageEvent<TranslationRequest>.data: TranslationRequest
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.TranslationRequest.tgt_lang: stringtgt_lang,
src_lang: stringsrc_lang: event: MessageEvent<TranslationRequest>event.MessageEvent<TranslationRequest>.data: TranslationRequest
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.TranslationRequest.src_lang: stringsrc_lang,
streamer: anystreamer, }); // Send the final result var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
.function postMessage(message: any, options?: WindowPostMessageOptions): void (+1 overload)
Posts a message to the given window. Messages can be structured objects, e.g. nested objects and arrays, can contain JavaScript values (strings, numbers, Date objects, etc), and can contain certain data objects such as File Blob, FileList, and ArrayBuffer objects. Objects listed in the transfer member of options are transferred, not just cloned, meaning that they are no longer usable on the sending side. A target origin can be specified using the targetOrigin member of options. If not provided, it defaults to "/". This default restricts the message to same-origin targets only. If the origin of the target window doesn't match the given target origin, the message is discarded, to avoid information leakage. To send the message to the target regardless of origin, set the target origin to "*". Throws a "DataCloneError" DOMException if transfer array contains duplicate objects or if message could not be cloned. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/postMessage)
postMessage
({
status: stringstatus: 'complete', output: anyoutput, }); } catch (function (local var) error: unknownerror) { var self: Window & typeof globalThis
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/self)
self
.function postMessage(message: any, options?: WindowPostMessageOptions): void (+1 overload)
Posts a message to the given window. Messages can be structured objects, e.g. nested objects and arrays, can contain JavaScript values (strings, numbers, Date objects, etc), and can contain certain data objects such as File Blob, FileList, and ArrayBuffer objects. Objects listed in the transfer member of options are transferred, not just cloned, meaning that they are no longer usable on the sending side. A target origin can be specified using the targetOrigin member of options. If not provided, it defaults to "/". This default restricts the message to same-origin targets only. If the origin of the target window doesn't match the given target origin, the message is discarded, to avoid information leakage. To send the message to the target regardless of origin, set the target origin to "*". Throws a "DataCloneError" DOMException if transfer array contains duplicate objects or if message could not be cloned. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/postMessage)
postMessage
({
status: stringstatus: 'error', error: stringerror: function (local var) error: unknownerror instanceof var Error: ErrorConstructorError ? function (local var) error: Errorerror.Error.message: stringmessage : 'An unknown error occurred' }); } });

3. Build the Interface

Create a clean interface with two main components:

Language Selector (src/components/LanguageSelector.vue)

<script setup lang="ts">
// Language codes follow the ISO 639-3 standard with script codes
const const LANGUAGES: Record<string, string>LANGUAGES: type Record<K extends keyof any, T> = { [P in K]: T; }
Construct a type with a set of properties K of type T
Record
<string, string> = {
"English": "eng_Latn", "French": "fra_Latn", "Spanish": "spa_Latn", "German": "deu_Latn", "Chinese": "zho_Hans", "Japanese": "jpn_Jpan", // Add more languages as needed }; // Strong typing for component props interface Props { Props.type: stringtype: string; Props.modelValue: stringmodelValue: string; } const defineProps: <Props>() => DefineProps<LooseRequired<Props>, never> (+2 overloads)
Vue `<script setup>` compiler macro for declaring component props. The expected argument is the same as the component `props` option. Example runtime declaration: ```js // using Array syntax const props = defineProps(['foo', 'bar']) // using Object syntax const props = defineProps({ foo: String, bar: { type: Number, required: true } }) ``` Equivalent type-based declaration: ```ts // will be compiled into equivalent runtime declarations const props = defineProps<{ foo?: string bar: number }>() ```
@see{@link https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits}This is only usable inside `<script setup>`, is compiled away in the output and should **not** be actually called at runtime.
defineProps
<Props>();
const const emit: __VLS_Emitemit = const defineEmits: <__VLS_Emit>() => __VLS_Emit (+2 overloads)
Vue `<script setup>` compiler macro for declaring a component's emitted events. The expected argument is the same as the component `emits` option. Example runtime declaration: ```js const emit = defineEmits(['change', 'update']) ``` Example type-based declaration: ```ts const emit = defineEmits<{ // <eventName>: <expected arguments> change: [] update: [value: number] // named tuple syntax }>() emit('change') emit('update', 1) ``` This is only usable inside `<script setup>`, is compiled away in the output and should **not** be actually called at runtime.
@see{@link https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits}
defineEmits
<{
(e: "update:modelValue"e: 'update:modelValue', value: stringvalue: string): void; }>(); const const onChange: (event: Event) => voidonChange = (event: Eventevent: Event) => { const const target: HTMLSelectElementtarget = event: Eventevent.Event.target: EventTarget | null
Returns the object to which event is dispatched (its target). [MDN Reference](https://developer.mozilla.org/docs/Web/API/Event/target)
target
as HTMLSelectElement;
const emit: (e: "update:modelValue", value: string) => voidemit('update:modelValue', const target: HTMLSelectElementtarget.HTMLSelectElement.value: string
Sets or retrieves the value which is returned to the server when the form control is submitted. [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLSelectElement/value)
value
);
}; </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="language-selector"> <label: LabelHTMLAttributes & ReservedPropslabel>{{ type: stringtype }}: </label: LabelHTMLAttributes & ReservedPropslabel> <select: SelectHTMLAttributes & ReservedPropsselect SelectHTMLAttributes.value?: any:value="modelValue: stringmodelValue" @onChange?: ((payload: Event) => void) | undefinedchange="const onChange: (event: Event) => voidonChange"> <option: OptionHTMLAttributes & ReservedPropsoption v-for="[const key: stringkey, const value: stringvalue] in var Object: ObjectConstructor
Provides functionality common to all JavaScript objects.
Object
.
ObjectConstructor.entries<string>(o: {
    [s: string]: string;
} | ArrayLike<string>): [string, string][] (+1 overload)
Returns an array of key/values of the enumerable own properties of an object
@paramo Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
entries
(const LANGUAGES: Record<string, string>LANGUAGES)"
key?: PropertyKey | undefined:key="const key: stringkey" OptionHTMLAttributes.value?: any:value="const value: stringvalue"> {{ const key: stringkey }} </option: OptionHTMLAttributes & ReservedPropsoption> </select: SelectHTMLAttributes & ReservedPropsselect> </div: HTMLAttributes & ReservedPropsdiv> </template> <style scoped> .language-selector { display: flex; align-items: center; gap: 0.5rem; } select { padding: 0.5rem; border-radius: 4px; border: 1px solid rgb(var(--color-border)); background-color: rgb(var(--color-card)); color: rgb(var(--color-text-base)); min-width: 200px; } </style>

Progress Bar (src/components/ProgressBar.vue)

<script setup lang="ts">

const defineProps: <__VLS_Props>() => DefineProps<LooseRequired<__VLS_Props>, never> (+2 overloads)
Vue `<script setup>` compiler macro for declaring component props. The expected argument is the same as the component `props` option. Example runtime declaration: ```js // using Array syntax const props = defineProps(['foo', 'bar']) // using Object syntax const props = defineProps({ foo: String, bar: { type: Number, required: true } }) ``` Equivalent type-based declaration: ```ts // will be compiled into equivalent runtime declarations const props = defineProps<{ foo?: string bar: number }>() ```
@see{@link https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits}This is only usable inside `<script setup>`, is compiled away in the output and should **not** be actually called at runtime.
defineProps
< {
text: stringtext: string; percentage: numberpercentage: number; }>(); </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="progress-container"> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="progress-bar" HTMLAttributes.style?: StyleValue:style="{ StandardLonghandProperties<string | number, string & {}>.width?: Property.Width<string | number> | undefined
The **`width`** CSS property sets an element's width. By default, it sets the width of the content area, but if `box-sizing` is set to `border-box`, it sets the width of the border area. **Syntax**: `auto | <length> | <percentage> | min-content | max-content | fit-content | fit-content(<length-percentage>)` **Initial value**: `auto` | Chrome | Firefox | Safari | Edge | IE | | :----: | :-----: | :----: | :----: | :---: | | **1** | **1** | **1** | **12** | **4** |
@seehttps://developer.mozilla.org/docs/Web/CSS/width
width
: `${percentage: numberpercentage}%` }">
{{ text: stringtext }} ({{ percentage: numberpercentage.Number.toFixed(fractionDigits?: number): string
Returns a string representing a number in fixed-point notation.
@paramfractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
toFixed
(2) }}%)
</div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </template> <style scoped> .progress-container { width: 100%; height: 20px; background-color: rgb(var(--color-card)); border-radius: 10px; margin: 10px 0; overflow: hidden; border: 1px solid rgb(var(--color-border)); } .progress-bar { height: 100%; background-color: rgb(var(--color-accent)); transition: width 0.3s ease; display: flex; align-items: center; padding: 0 10px; color: rgb(var(--color-text-base)); font-size: 0.9rem; white-space: nowrap; } .progress-bar:hover { background-color: rgb(var(--color-card-muted)); } </style>

4. Put It All Together

In your main app file:

<script setup lang="ts">
import { function ref<T>(value: T): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
, const onMounted: CreateHook<any>onMounted, const onUnmounted: CreateHook<any>onUnmounted, function watch<T, Immediate extends Readonly<boolean> = false>(source: WatchSource<T>, cb: WatchCallback<T, MaybeUndefined<T, Immediate>>, options?: WatchOptions<Immediate>): WatchHandle (+3 overloads)watch,
const computed: {
    <T>(getter: ComputedGetter<T>, debugOptions?: DebuggerOptions): ComputedRef<T>;
    <T, S = T>(options: WritableComputedOptions<T, S>, debugOptions?: DebuggerOptions): WritableComputedRef<T, S>;
}
computed
} from 'vue';
import import LanguageSelectorLanguageSelector from './components/LanguageSelector.vue'; import import ProgressBarProgressBar from './components/ProgressBar.vue'; interface ProgressItem { ProgressItem.file: stringfile: string; ProgressItem.progress: numberprogress: number; } // State const
const worker: Ref<{
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null, Worker | ... 1 more ... | null>
worker
=
ref<Worker | null>(value: Worker | null): Ref<{
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    ... 5 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null, Worker | ... 1 more ... | null> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
<Worker | null>(null);
const const ready: Ref<boolean | null, boolean | null>ready = ref<boolean | null>(value: boolean | null): Ref<boolean | null, boolean | null> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
<boolean | null>(null);
const const disabled: Ref<boolean, boolean>disabled = ref<boolean>(value: boolean): Ref<boolean, boolean> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
(false);
const
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
=
ref<Map<string, ProgressItem>>(value: Map<string, ProgressItem>): Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<...>>, Map<...> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
<interface Map<K, V>Map<string, ProgressItem>>(new
var Map: MapConstructor
new () => Map<any, any> (+3 overloads)
Map
());
const const input: Ref<string, string>input = ref<string>(value: string): Ref<string, string> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
('I love walking my dog.');
const const sourceLanguage: Ref<string, string>sourceLanguage = ref<string>(value: string): Ref<string, string> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
('eng_Latn');
const const targetLanguage: Ref<string, string>targetLanguage = ref<string>(value: string): Ref<string, string> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
('fra_Latn');
const const output: Ref<string, string>output = ref<string>(value: string): Ref<string, string> (+1 overload)
Takes an inner value and returns a reactive and mutable ref object, which has a single property `.value` that points to the inner value.
@paramvalue - The object to wrap in the ref.@see{@link https://vuejs.org/api/reactivity-core.html#ref}
ref
('');
// Computed property for progress items array const
const progressItemsArray: ComputedRef<{
    file: string;
    progress: number;
}[]>
progressItemsArray
=
computed<{
    file: string;
    progress: number;
}[]>(getter: ComputedGetter<{
    file: string;
    progress: number;
}[]>, debugOptions?: DebuggerOptions): ComputedRef<...> (+1 overload)
Takes a getter function and returns a readonly reactive ref object for the returned value from the getter. It can also take an object with get and set functions to create a writable ref object.
@example```js // Creating a readonly computed ref: const count = ref(1) const plusOne = computed(() => count.value + 1) console.log(plusOne.value) // 2 plusOne.value++ // error ``` ```js // Creating a writable computed ref: const count = ref(1) const plusOne = computed({ get: () => count.value + 1, set: (val) => { count.value = val - 1 } }) plusOne.value = 1 console.log(count.value) // 0 ```@paramgetter - Function that produces the next value.@paramdebugOptions - For debugging. See {@link https://vuejs.org/guide/extras/reactivity-in-depth.html#computed-debugging}.@see{@link https://vuejs.org/api/reactivity-core.html#computed}
computed
(() => {
return var Array: ArrayConstructorArray.
ArrayConstructor.from<{
    file: string;
    progress: number;
}>(iterable: Iterable<{
    file: string;
    progress: number;
}> | ArrayLike<{
    file: string;
    progress: number;
}>): {
    file: string;
    progress: number;
}[] (+3 overloads)
Creates an array from an iterable object.
@paramiterable An iterable object to convert to an array.
from
(
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
value
.
Map<string, { file: string; progress: number; }>.values(): MapIterator<{
    file: string;
    progress: number;
}>
Returns an iterable of values in the map
values
());
}); // Watch progress items
watch<{
    file: string;
    progress: number;
}[], false>(source: WatchSource<{
    file: string;
    progress: number;
}[]>, cb: WatchCallback<{
    file: string;
    progress: number;
}[], {
    file: string;
    progress: number;
}[]>, options?: WatchOptions<...> | undefined): WatchHandle (+3 overloads)
watch
(
const progressItemsArray: ComputedRef<{
    file: string;
    progress: number;
}[]>
progressItemsArray
, (
newItems: {
    file: string;
    progress: number;
}[]
newItems
) => {
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
('Progress items updated:',
newItems: {
    file: string;
    progress: number;
}[]
newItems
);
}, { WatchOptions<Immediate = boolean>.deep?: number | boolean | undefineddeep: true }); // Translation handler const const translate: () => voidtranslate = () => { if (!
const worker: Ref<{
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null, Worker | ... 1 more ... | null>
worker
.
Ref<{ onmessage: ((this: Worker, ev: MessageEvent) => any) | null; onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null; postMessage: { (message: any, transfer: Transferable[]): void; (message: any, options?: StructuredSerializeOptions): void; }; ... 4 more ...; onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null; } | null, Worker | ... 1 more ... | null>.value: {
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null
value
) return;
const disabled: Ref<boolean, boolean>disabled.Ref<boolean, boolean>.value: booleanvalue = true; const output: Ref<string, string>output.Ref<string, string>.value: stringvalue = '';
const worker: Ref<{
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null, Worker | ... 1 more ... | null>
worker
.
Ref<{ onmessage: ((this: Worker, ev: MessageEvent) => any) | null; onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null; postMessage: { (message: any, transfer: Transferable[]): void; (message: any, options?: StructuredSerializeOptions): void; }; ... 4 more ...; onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null; } | null, Worker | ... 1 more ... | null>.value: {
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
}
value
.function postMessage(message: any, options?: StructuredSerializeOptions): void (+1 overload)
Clones message and transmits it to worker's global environment. transfer can be passed as a list of objects that are to be transferred rather than cloned. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/postMessage)
postMessage
({
text: stringtext: const input: Ref<string, string>input.Ref<string, string>.value: stringvalue, src_lang: stringsrc_lang: const sourceLanguage: Ref<string, string>sourceLanguage.Ref<string, string>.value: stringvalue, tgt_lang: stringtgt_lang: const targetLanguage: Ref<string, string>targetLanguage.Ref<string, string>.value: stringvalue, }); }; // Worker message handler const const onMessageReceived: (e: MessageEvent) => voidonMessageReceived = (e: MessageEvent<any>e: interface MessageEvent<T = any>
A message received by a target object. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent)
@sincev15.0.0
MessageEvent
) => {
switch (e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.status) {
case 'initiate': const ready: Ref<boolean | null, boolean | null>ready.Ref<boolean | null, boolean | null>.value: boolean | nullvalue = false;
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
value
.
Map<string, { file: string; progress: number; }>.set(key: string, value: {
    file: string;
    progress: number;
}): Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set
(e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.file, {
file: stringfile: e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.file,
progress: numberprogress: 0 });
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>)
value
= new
var Map: MapConstructor
new <string, {
    file: string;
    progress: number;
}>(iterable?: Iterable<readonly [string, {
    file: string;
    progress: number;
}]> | null | undefined) => Map<string, {
    file: string;
    progress: number;
}> (+3 overloads)
Map
(
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
value
);
break; case 'progress': if (
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
value
.Map<string, { file: string; progress: number; }>.has(key: string): boolean
@returnsboolean indicating whether an element with the specified key exists or not.
has
(e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.file)) {
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
value
.
Map<string, { file: string; progress: number; }>.set(key: string, value: {
    file: string;
    progress: number;
}): Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set
(e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.file, {
file: stringfile: e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.file,
progress: numberprogress: e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.progress
});
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>)
value
= new
var Map: MapConstructor
new <string, {
    file: string;
    progress: number;
}>(iterable?: Iterable<readonly [string, {
    file: string;
    progress: number;
}]> | null | undefined) => Map<string, {
    file: string;
    progress: number;
}> (+3 overloads)
Map
(
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
value
);
} break; case 'done':
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
value
.Map<string, { file: string; progress: number; }>.delete(key: string): boolean
@returnstrue if an element in the Map existed and has been removed, or false if the element does not exist.
delete
(e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.file);
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>)
value
= new
var Map: MapConstructor
new <string, {
    file: string;
    progress: number;
}>(iterable?: Iterable<readonly [string, {
    file: string;
    progress: number;
}]> | null | undefined) => Map<string, {
    file: string;
    progress: number;
}> (+3 overloads)
Map
(
const progressItems: Ref<Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, {
    file: string;
    progress: number;
}> & Omit<...>)>
progressItems
.
Ref<Map<string, { file: string; progress: number; }> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>, Map<string, ProgressItem> | (Map<string, { file: string; progress: number; }> & Omit<...>)>.value: Map<string, {
    file: string;
    progress: number;
}> & Omit<Map<string, ProgressItem>, keyof Map<any, any>>
value
);
break; case 'ready': const ready: Ref<boolean | null, boolean | null>ready.Ref<boolean | null, boolean | null>.value: boolean | nullvalue = true; break; case 'update': const output: Ref<string, string>output.Ref<string, string>.value: stringvalue += e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.output;
break; case 'complete': const disabled: Ref<boolean, boolean>disabled.Ref<boolean, boolean>.value: booleanvalue = false; break; case 'error': var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v22.x/lib/console.js)
console
.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
('Translation error:', e: MessageEvent<any>e.MessageEvent<any>.data: any
Returns the data of the message. [MDN Reference](https://developer.mozilla.org/docs/Web/API/MessageEvent/data)
data
.error);
const disabled: Ref<boolean, boolean>disabled.Ref<boolean, boolean>.value: booleanvalue = false; break; } }; // Lifecycle hooks function onMounted(hook: any, target?: ComponentInternalInstance | null): voidonMounted(() => {
const worker: Ref<{
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null, Worker | ... 1 more ... | null>
worker
.
Ref<{ onmessage: ((this: Worker, ev: MessageEvent) => any) | null; onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null; postMessage: { (message: any, transfer: Transferable[]): void; (message: any, options?: StructuredSerializeOptions): void; }; ... 4 more ...; onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null; } | null, Worker | ... 1 more ... | null>.value: Worker | {
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null
value
= new var Worker: new (scriptURL: string | URL, options?: WorkerOptions) => Worker
This Web Workers API interface represents a background task that can be easily created and can send messages back to its creator. Creating a worker is as simple as calling the Worker() constructor and specifying a script to be run in the worker thread. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker)
Worker
(
new var URL: new (url: string | URL, base?: string | URL) => URL
The URL interface represents an object providing static methods used for creating object URLs. [MDN Reference](https://developer.mozilla.org/docs/Web/API/URL) `URL` class is a global reference for `import { URL } from 'url'` https://nodejs.org/api/url.html#the-whatwg-url-api
@sincev10.0.0
URL
('./workers/translation.worker.ts', import.meta.ImportMeta.url: string
The absolute `file:` URL of the module.
url
),
{ WorkerOptions.type?: WorkerType | undefinedtype: 'module' } );
const worker: Ref<{
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null, Worker | ... 1 more ... | null>
worker
.
Ref<{ onmessage: ((this: Worker, ev: MessageEvent) => any) | null; onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null; postMessage: { (message: any, transfer: Transferable[]): void; (message: any, options?: StructuredSerializeOptions): void; }; ... 4 more ...; onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null; } | null, Worker | ... 1 more ... | null>.value: {
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
}
value
.addEventListener<"message">(type: "message", listener: (this: Worker, ev: MessageEvent<any>) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched. The options argument sets listener-specific options. For compatibility this can be a boolean, in which case the method behaves exactly as if the value was specified as options's capture. When set to true, options's capture prevents callback from being invoked when the event's eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event's eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event's eventPhase attribute value is AT_TARGET. When set to true, options's passive indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in § 2.8 Observing event listeners. When set to true, options's once indicates that the callback will only be invoked once after which the event listener will be removed. If an AbortSignal is passed for options's signal, then the event listener will be removed when signal is aborted. The event listener is appended to target's event listener list and is not appended if it has the same type, callback, and capture. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener)
addEventListener
('message', const onMessageReceived: (e: MessageEvent) => voidonMessageReceived);
}); function onUnmounted(hook: any, target?: ComponentInternalInstance | null): voidonUnmounted(() => {
const worker: Ref<{
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null, Worker | ... 1 more ... | null>
worker
.
Ref<{ onmessage: ((this: Worker, ev: MessageEvent) => any) | null; onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null; postMessage: { (message: any, transfer: Transferable[]): void; (message: any, options?: StructuredSerializeOptions): void; }; ... 4 more ...; onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null; } | null, Worker | ... 1 more ... | null>.value: {
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null
value
?.removeEventListener<K>(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, options?: boolean | EventListenerOptions): void (+1 overload)
Removes the event listener in target's event listener list with the same type, callback, and options. [MDN Reference](https://developer.mozilla.org/docs/Web/API/EventTarget/removeEventListener)
removeEventListener
('message', const onMessageReceived: (e: MessageEvent) => voidonMessageReceived);
const worker: Ref<{
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null, Worker | ... 1 more ... | null>
worker
.
Ref<{ onmessage: ((this: Worker, ev: MessageEvent) => any) | null; onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null; postMessage: { (message: any, transfer: Transferable[]): void; (message: any, options?: StructuredSerializeOptions): void; }; ... 4 more ...; onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null; } | null, Worker | ... 1 more ... | null>.value: {
    onmessage: ((this: Worker, ev: MessageEvent) => any) | null;
    onmessageerror: ((this: Worker, ev: MessageEvent) => any) | null;
    postMessage: {
        (message: any, transfer: Transferable[]): void;
        (message: any, options?: StructuredSerializeOptions): void;
    };
    ... 4 more ...;
    onerror: ((this: AbstractWorker, ev: ErrorEvent) => any) | null;
} | null
value
?.function terminate(): void
Aborts worker's associated global environment. [MDN Reference](https://developer.mozilla.org/docs/Web/API/Worker/terminate)
terminate
();
}); </script> <template> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="app"> <h1: HTMLAttributes & ReservedPropsh1>Transformers.js</h1: HTMLAttributes & ReservedPropsh1> <h2: HTMLAttributes & ReservedPropsh2>ML-powered multilingual translation in Vue!</h2: HTMLAttributes & ReservedPropsh2> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="container"> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="language-container"> <import LanguageSelectorLanguageSelector type: stringtype="Source" modelValue: stringv-model="const sourceLanguage: Ref<string, string>sourceLanguage" /> <import LanguageSelectorLanguageSelector type: stringtype="Target" modelValue: stringv-model="const targetLanguage: Ref<string, string>targetLanguage" /> </div: HTMLAttributes & ReservedPropsdiv> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="textbox-container"> <textarea: TextareaHTMLAttributes & ReservedPropstextarea TextareaHTMLAttributes.value?: string | number | readonly string[] | null | undefinedv-model="const input: Ref<string, string>input" TextareaHTMLAttributes.rows?: Numberish | undefinedrows="3" TextareaHTMLAttributes.placeholder?: string | undefinedplaceholder="Enter text to translate..." /> <textarea: TextareaHTMLAttributes & ReservedPropstextarea TextareaHTMLAttributes.value?: string | number | readonly string[] | null | undefinedv-model="const output: Ref<string, string>output" TextareaHTMLAttributes.rows?: Numberish | undefinedrows="3" TextareaHTMLAttributes.readonly?: Booleanish | undefinedreadonly TextareaHTMLAttributes.placeholder?: string | undefinedplaceholder="Translation will appear here..." /> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> <button: ButtonHTMLAttributes & ReservedPropsbutton ButtonHTMLAttributes.disabled?: Booleanish | undefined:disabled="const disabled: Ref<boolean, boolean>disabled || const ready: Ref<boolean | null, boolean | null>ready === false" @onClick?: ((payload: MouseEvent) => void) | undefinedclick="const translate: () => voidtranslate" > {{ const ready: Ref<boolean | null, boolean | null>ready === false ? 'Loading...' : 'Translate' }} </button: ButtonHTMLAttributes & ReservedPropsbutton> <div: HTMLAttributes & ReservedPropsdiv HTMLAttributes.class?: anyclass="progress-bars-container"> <label: LabelHTMLAttributes & ReservedPropslabel v-if="const ready: Ref<boolean | null, boolean | null>ready === false"> Loading models... (only run once) </label: LabelHTMLAttributes & ReservedPropslabel> <div: HTMLAttributes & ReservedPropsdiv v-for="
const item: {
    file: string;
    progress: number;
}
item
in
const progressItemsArray: ComputedRef<{
    file: string;
    progress: number;
}[]>
progressItemsArray
"
key?: PropertyKey | undefined:key="
const item: {
    file: string;
    progress: number;
}
item
.file: stringfile"
> <import ProgressBarProgressBar text: string:text="
const item: {
    file: string;
    progress: number;
}
item
.file: stringfile"
percentage: number:percentage="
const item: {
    file: string;
    progress: number;
}
item
.progress: numberprogress"
/> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </div: HTMLAttributes & ReservedPropsdiv> </template> <style scoped> .app { max-width: 800px; margin: 0 auto; padding: 2rem; text-align: center; } .container { margin: 2rem 0; } .language-container { display: flex; justify-content: center; gap: 2rem; margin-bottom: 1rem; } .textbox-container { display: flex; gap: 1rem; } textarea { flex: 1; padding: 0.5rem; border-radius: 4px; border: 1px solid rgb(var(--color-border)); background-color: rgb(var(--color-card)); color: rgb(var(--color-text-base)); font-size: 1rem; min-height: 100px; resize: vertical; } button { padding: 0.5rem 2rem; font-size: 1.1rem; cursor: pointer; background-color: rgb(var(--color-accent)); color: rgb(var(--color-text-base)); border: none; border-radius: 4px; transition: background-color 0.3s; } button:hover:not(:disabled) { background-color: rgb(var(--color-card-muted)); } button:disabled { opacity: 0.6; cursor: not-allowed; } .progress-bars-container { margin-top: 2rem; } h1 { color: rgb(var(--color-text-base)); margin-bottom: 0.5rem; } h2 { color: rgb(var(--color-card-muted)); font-size: 1.2rem; font-weight: normal; margin-top: 0; } </style>

Step 5: Optimizing the Build

Configure Vite to handle our Web Workers and TypeScript efficiently:

import { function defineConfig(config: UserConfig): UserConfig (+3 overloads)
Type helper to make it easier to use vite.config.ts accepts a direct {@link UserConfig } object, or a function that returns it. The function receives a {@link ConfigEnv } object.
defineConfig
} from 'vite'
import import vuevue from '@vitejs/plugin-vue' export default function defineConfig(config: UserConfig): UserConfig (+3 overloads)
Type helper to make it easier to use vite.config.ts accepts a direct {@link UserConfig } object, or a function that returns it. The function receives a {@link ConfigEnv } object.
defineConfig
({
UserConfig.plugins?: PluginOption[] | undefined
Array of vite plugins to use.
plugins
: [import vuevue()],
UserConfig.worker?: {
    format?: "es" | "iife";
    plugins?: () => PluginOption[];
    rollupOptions?: Omit<RollupOptions, "plugins" | "input" | "onwarn" | "preserveEntrySignatures">;
} | undefined
Worker bundle options
worker
: {
format?: "es" | "iife" | undefined
Output format for worker bundle
@default'iife'
format
: 'es', // Use ES modules format for workers
plugins?: (() => PluginOption[]) | undefined
Vite plugins that apply to worker bundle. The plugins returned by this function should be new instances every time it is called, because they are used for each rollup worker bundling process.
plugins
: [] // No additional plugins needed for workers
}, UserConfig.optimizeDeps?: DepOptimizationOptions | undefined
Dep optimization options
optimizeDeps
: {
DepOptimizationConfig.exclude?: string[] | undefined
Do not optimize these dependencies (must be resolvable import paths, cannot be globs).
exclude
: ['@huggingface/transformers'] // Prevent Vite from trying to bundle Transformers.js
} })

How It Works

  1. You type text and select languages
  2. The text goes to a Web Worker
  3. Transformers.js loads the AI model (once)
  4. The model translates your text
  5. You see the translation appear in real time

The translator works offline after the first run. No data leaves your browser. No API keys needed.

Try It Yourself

Loading project...

Want to explore the code further? Check out the complete source code on GitHub.

Want to learn more? Explore these resources:

Related Posts