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
- Vue 3 for the interface
- Transformers.js to run AI models locally
- Web Workers to handle heavy processing
- NLLB-200, Meta’s translation model
Building the 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 pipeline
pipeline, import TextStreamer
TextStreamer, import TranslationPipeline
TranslationPipeline } from '@huggingface/transformers';
import type { import PipelineType
PipelineType, import ProgressCallback
ProgressCallback } from '@huggingface/transformers';
// Singleton pattern for the translation pipeline
class class MyTranslationPipeline
MyTranslationPipeline {
static MyTranslationPipeline.task: PipelineType
task: import PipelineType
PipelineType = 'translation';
// We use the distilled model for faster loading and inference
static MyTranslationPipeline.model: string
model = 'Xenova/nllb-200-distilled-600M';
static MyTranslationPipeline.instance: any
instance: import TranslationPipeline
TranslationPipeline | null = null;
static async MyTranslationPipeline.getInstance(progress_callback?: ProgressCallback): Promise<any>
getInstance(progress_callback: any
progress_callback?: import ProgressCallback
ProgressCallback) {
if (!this.MyTranslationPipeline.instance: any
instance) {
this.MyTranslationPipeline.instance: any
instance = await import pipeline
pipeline(this.MyTranslationPipeline.task: PipelineType
task, this.MyTranslationPipeline.model: string
model, { progress_callback: any
progress_callback }) as import TranslationPipeline
TranslationPipeline;
}
return this.MyTranslationPipeline.instance: any
instance;
}
}
// Type definitions for worker messages
interface TranslationRequest {
TranslationRequest.text: string
text: string;
TranslationRequest.src_lang: string
src_lang: string;
TranslationRequest.tgt_lang: string
tgt_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)MessageEvent<TranslationRequest>) => {
try {
// Initialize the translation pipeline with progress tracking
const const translator: any
translator = await class MyTranslationPipeline
MyTranslationPipeline.MyTranslationPipeline.getInstance(progress_callback?: ProgressCallback): Promise<any>
getInstance(x: any
x => {
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: any
x);
});
// Configure streaming for real-time translation updates
const const streamer: any
streamer = new import TextStreamer
TextStreamer(const translator: any
translator.tokenizer, {
skip_prompt: boolean
skip_prompt: true,
skip_special_tokens: boolean
skip_special_tokens: true,
callback_function: (text: string) => void
callback_function: (text: string
text: 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: string
status: 'update',
output: string
output: text: string
text
});
}
});
// Perform the translation
const const output: any
output = await const translator: any
translator(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: string
text, {
// @ts-ignore - Type definitions are incomplete
tgt_lang: string
tgt_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: string
tgt_lang,
src_lang: string
src_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: string
src_lang,
streamer: any
streamer,
});
// 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: string
status: 'complete',
output: any
output,
});
} catch (function (local var) error: unknown
error) {
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: string
status: 'error',
error: string
error: function (local var) error: unknown
error instanceof var Error: ErrorConstructor
Error ? function (local var) error: Error
error.Error.message: string
message : '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 TRecord<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: string
type: string;
Props.modelValue: string
modelValue: 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
}>()
```defineProps<Props>();
const const emit: __VLS_Emit
emit = 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.defineEmits<{
(e: "update:modelValue"
e: 'update:modelValue', value: string
value: string): void;
}>();
const const onChange: (event: Event) => void
onChange = (event: Event
event: Event) => {
const const target: HTMLSelectElement
target = event: Event
event.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) => void
emit('update:modelValue', const target: HTMLSelectElement
target.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 & ReservedProps
div HTMLAttributes.class?: any
class="language-selector">
<label: LabelHTMLAttributes & ReservedProps
label>{{ type: string
type }}: </label: LabelHTMLAttributes & ReservedProps
label>
<select: SelectHTMLAttributes & ReservedProps
select SelectHTMLAttributes.value?: any
:value="modelValue: string
modelValue" @onChange?: ((payload: Event) => void) | undefined
change="const onChange: (event: Event) => void
onChange">
<option: OptionHTMLAttributes & ReservedProps
option v-for="[const key: string
key, const value: string
value] 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 objectentries(const LANGUAGES: Record<string, string>
LANGUAGES)"
key?: PropertyKey | undefined
:key="const key: string
key"
OptionHTMLAttributes.value?: any
:value="const value: string
value">
{{ const key: string
key }}
</option: OptionHTMLAttributes & ReservedProps
option>
</select: SelectHTMLAttributes & ReservedProps
select>
</div: HTMLAttributes & ReservedProps
div>
</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
}>()
```defineProps< {
text: string
text: string;
percentage: number
percentage: number;
}>();
</script>
<template>
<div: HTMLAttributes & ReservedProps
div HTMLAttributes.class?: any
class="progress-container">
<div: HTMLAttributes & ReservedProps
div HTMLAttributes.class?: any
class="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** |width: `${percentage: number
percentage}%` }">
{{ text: string
text }} ({{ percentage: number
percentage.Number.toFixed(fractionDigits?: number): string
Returns a string representing a number in fixed-point notation.toFixed(2) }}%)
</div: HTMLAttributes & ReservedProps
div>
</div: HTMLAttributes & ReservedProps
div>
</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.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 LanguageSelector
LanguageSelector from './components/LanguageSelector.vue';
import import ProgressBar
ProgressBar from './components/ProgressBar.vue';
interface ProgressItem {
ProgressItem.file: string
file: string;
ProgressItem.progress: number
progress: 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.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.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.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.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.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.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.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.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.computed(() => {
return var Array: ArrayConstructor
Array.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.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 mapvalues());
});
// 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
```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.log('Progress items updated:', newItems: {
file: string;
progress: number;
}[]
newItems);
}, { WatchOptions<Immediate = boolean>.deep?: number | boolean | undefined
deep: true });
// Translation handler
const const translate: () => void
translate = () => {
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: boolean
value = true;
const output: Ref<string, string>
output.Ref<string, string>.value: string
value = '';
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: string
text: const input: Ref<string, string>
input.Ref<string, string>.value: string
value,
src_lang: string
src_lang: const sourceLanguage: Ref<string, string>
sourceLanguage.Ref<string, string>.value: string
value,
tgt_lang: string
tgt_lang: const targetLanguage: Ref<string, string>
targetLanguage.Ref<string, string>.value: string
value,
});
};
// Worker message handler
const const onMessageReceived: (e: MessageEvent) => void
onMessageReceived = (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)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 | null
value = 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: string
file: 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: number
progress: 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
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: string
file: 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: number
progress: 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
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 | null
value = true;
break;
case 'update':
const output: Ref<string, string>
output.Ref<string, string>.value: string
value += 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: boolean
value = 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
```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.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: boolean
value = false;
break;
}
};
// Lifecycle hooks
function onMounted(hook: any, target?: ComponentInternalInstance | null): void
onMounted(() => {
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-apiURL('./workers/translation.worker.ts', import.meta.ImportMeta.url: string
The absolute `file:` URL of the module.url),
{ WorkerOptions.type?: WorkerType | undefined
type: '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) => void
onMessageReceived);
});
function onUnmounted(hook: any, target?: ComponentInternalInstance | null): void
onUnmounted(() => {
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) => void
onMessageReceived);
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 & ReservedProps
div HTMLAttributes.class?: any
class="app">
<h1: HTMLAttributes & ReservedProps
h1>Transformers.js</h1: HTMLAttributes & ReservedProps
h1>
<h2: HTMLAttributes & ReservedProps
h2>ML-powered multilingual translation in Vue!</h2: HTMLAttributes & ReservedProps
h2>
<div: HTMLAttributes & ReservedProps
div HTMLAttributes.class?: any
class="container">
<div: HTMLAttributes & ReservedProps
div HTMLAttributes.class?: any
class="language-container">
<import LanguageSelector
LanguageSelector
type: string
type="Source"
modelValue: string
v-model="const sourceLanguage: Ref<string, string>
sourceLanguage"
/>
<import LanguageSelector
LanguageSelector
type: string
type="Target"
modelValue: string
v-model="const targetLanguage: Ref<string, string>
targetLanguage"
/>
</div: HTMLAttributes & ReservedProps
div>
<div: HTMLAttributes & ReservedProps
div HTMLAttributes.class?: any
class="textbox-container">
<textarea: TextareaHTMLAttributes & ReservedProps
textarea
TextareaHTMLAttributes.value?: string | number | readonly string[] | null | undefined
v-model="const input: Ref<string, string>
input"
TextareaHTMLAttributes.rows?: Numberish | undefined
rows="3"
TextareaHTMLAttributes.placeholder?: string | undefined
placeholder="Enter text to translate..."
/>
<textarea: TextareaHTMLAttributes & ReservedProps
textarea
TextareaHTMLAttributes.value?: string | number | readonly string[] | null | undefined
v-model="const output: Ref<string, string>
output"
TextareaHTMLAttributes.rows?: Numberish | undefined
rows="3"
TextareaHTMLAttributes.readonly?: Booleanish | undefined
readonly
TextareaHTMLAttributes.placeholder?: string | undefined
placeholder="Translation will appear here..."
/>
</div: HTMLAttributes & ReservedProps
div>
</div: HTMLAttributes & ReservedProps
div>
<button: ButtonHTMLAttributes & ReservedProps
button
ButtonHTMLAttributes.disabled?: Booleanish | undefined
:disabled="const disabled: Ref<boolean, boolean>
disabled || const ready: Ref<boolean | null, boolean | null>
ready === false"
@onClick?: ((payload: MouseEvent) => void) | undefined
click="const translate: () => void
translate"
>
{{ const ready: Ref<boolean | null, boolean | null>
ready === false ? 'Loading...' : 'Translate' }}
</button: ButtonHTMLAttributes & ReservedProps
button>
<div: HTMLAttributes & ReservedProps
div HTMLAttributes.class?: any
class="progress-bars-container">
<label: LabelHTMLAttributes & ReservedProps
label v-if="const ready: Ref<boolean | null, boolean | null>
ready === false">
Loading models... (only run once)
</label: LabelHTMLAttributes & ReservedProps
label>
<div: HTMLAttributes & ReservedProps
div
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: string
file"
>
<import ProgressBar
ProgressBar
text: string
:text="const item: {
file: string;
progress: number;
}
item.file: string
file"
percentage: number
:percentage="const item: {
file: string;
progress: number;
}
item.progress: number
progress"
/>
</div: HTMLAttributes & ReservedProps
div>
</div: HTMLAttributes & ReservedProps
div>
</div: HTMLAttributes & ReservedProps
div>
</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 vue
vue 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 vue
vue()],
UserConfig.worker?: {
format?: "es" | "iife";
plugins?: () => PluginOption[];
rollupOptions?: Omit<RollupOptions, "plugins" | "input" | "onwarn" | "preserveEntrySignatures">;
} | undefined
Worker bundle optionsworker: {
format?: "es" | "iife" | undefined
Output format for worker bundleformat: '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 optionsoptimizeDeps: {
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
- You type text and select languages
- The text goes to a Web Worker
- Transformers.js loads the AI model (once)
- The model translates your text
- 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
Want to explore the code further? Check out the complete source code on GitHub.
Want to learn more? Explore these resources: