Translate and Localize Content
LM-Kit.NET provides built-in translation that detects the source language automatically and translates to any supported target language. Everything runs locally, so sensitive documents (legal contracts, medical records, internal communications) never leave your infrastructure. This tutorial builds a working translation tool with language detection, streaming output, and batch processing.
Why Local Translation Matters
Two enterprise problems that on-device translation solves:
- Sensitive document translation. Legal contracts, patent filings, medical records, and M&A documents require translation but cannot be sent to cloud services. Cloud translation providers may retain submitted text to improve their models. Local translation eliminates that data exposure entirely.
- Multilingual support without per-word costs. Cloud translation APIs charge per character. Translating product catalogs, help centers, and marketing content across 10+ languages adds up quickly. A local model handles unlimited volume at fixed hardware cost.
Prerequisites
| Requirement | Minimum |
|---|---|
| .NET SDK | 8.0+ |
| VRAM | 4+ GB |
| Disk | ~3 GB free for model download |
Use a multilingual model. qwen3:4b and gemma3:4b both support 30+ languages.
Step 1: Create the Project
dotnet new console -n TranslationQuickstart
cd TranslationQuickstart
dotnet add package LM-Kit.NET
Step 2: Basic Translation with Language Detection
This program detects the source language and translates to a target language of your choice.
using System.Text;
using LMKit.Model;
using LMKit.TextGeneration;
using LMKit.TextGeneration.Chat;
using LMKit.Translation;
LMKit.Licensing.LicenseManager.SetLicenseKey("");
Console.InputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;
// ──────────────────────────────────────
// 1. Load a multilingual model
// ──────────────────────────────────────
Console.WriteLine("Loading model...");
using LM model = LM.LoadFromModelID("qwen3:4b",
downloadingProgress: (_, len, read) =>
{
if (len.HasValue) Console.Write($"\r Downloading: {(double)read / len.Value * 100:F1}% ");
return true;
},
loadingProgress: p => { Console.Write($"\r Loading: {p * 100:F0}% "); return true; });
Console.WriteLine("\n");
// ──────────────────────────────────────
// 2. Create translator with streaming
// ──────────────────────────────────────
var translator = new TextTranslation(model);
translator.AfterTextCompletion += (_, e) =>
{
if (e.SegmentType == TextSegmentType.UserVisible)
Console.Write(e.Text);
};
// ──────────────────────────────────────
// 3. Translation loop
// ──────────────────────────────────────
Console.WriteLine("Enter text to translate (or 'quit' to exit).");
Console.WriteLine("Target language defaults to English. Type 'lang:French' to change.\n");
Language targetLanguage = Language.English;
while (true)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write($"[→ {targetLanguage}] Text: ");
Console.ResetColor();
string? input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input) || input.Equals("quit", StringComparison.OrdinalIgnoreCase))
break;
// Allow changing target language
if (input.StartsWith("lang:", StringComparison.OrdinalIgnoreCase))
{
string langName = input.Substring(5).Trim();
if (Enum.TryParse<Language>(langName, ignoreCase: true, out Language parsed))
{
targetLanguage = parsed;
Console.WriteLine($" Target language set to {targetLanguage}\n");
}
else
{
Console.WriteLine($" Unknown language: {langName}\n");
}
continue;
}
// Detect source language
Language detected = translator.DetectLanguage(input);
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($" Detected: {detected} ({translator.Confidence:P0})");
Console.ResetColor();
// Translate
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write(" Translation: ");
Console.ResetColor();
string result = translator.Translate(input, targetLanguage);
Console.WriteLine("\n");
}
Step 3: Translating Between Specific Language Pairs
Language detection is automatic, but you can control both source detection and target:
using System.Text;
using LMKit.Model;
using LMKit.TextGeneration;
using LMKit.TextGeneration.Chat;
using LMKit.Translation;
LMKit.Licensing.LicenseManager.SetLicenseKey("");
Console.InputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;
// ──────────────────────────────────────
// 1. Load a multilingual model
// ──────────────────────────────────────
Console.WriteLine("Loading model...");
using LM model = LM.LoadFromModelID("qwen3:4b",
downloadingProgress: (_, len, read) =>
{
if (len.HasValue) Console.Write($"\r Downloading: {(double)read / len.Value * 100:F1}% ");
return true;
},
loadingProgress: p => { Console.Write($"\r Loading: {p * 100:F0}% "); return true; });
Console.WriteLine("\n");
// ──────────────────────────────────────
// 2. Create translator with streaming
// ──────────────────────────────────────
var translator = new TextTranslation(model);
translator.AfterTextCompletion += (_, e) =>
{
if (e.SegmentType == TextSegmentType.UserVisible)
Console.Write(e.Text);
};
// ──────────────────────────────────────
// 3. Translation loop
// ──────────────────────────────────────
Console.WriteLine("Enter text to translate (or 'quit' to exit).");
Console.WriteLine("Target language defaults to English. Type 'lang:French' to change.\n");
Language targetLanguage = Language.English;
while (true)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write($"[→ {targetLanguage}] Text: ");
Console.ResetColor();
string? input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input) || input.Equals("quit", StringComparison.OrdinalIgnoreCase))
break;
// Allow changing target language
if (input.StartsWith("lang:", StringComparison.OrdinalIgnoreCase))
{
string langName = input.Substring(5).Trim();
if (Enum.TryParse<Language>(langName, ignoreCase: true, out Language parsed))
{
targetLanguage = parsed;
Console.WriteLine($" Target language set to {targetLanguage}\n");
}
else
{
Console.WriteLine($" Unknown language: {langName}\n");
}
continue;
}
// Detect source language
Language detected = translator.DetectLanguage(input);
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($" Detected: {detected} ({translator.Confidence:P0})");
Console.ResetColor();
// Translate
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write(" Translation: ");
Console.ResetColor();
string result = translator.Translate(input, targetLanguage);
Console.WriteLine("\n");
}
// Detect among a restricted set of languages (faster, more accurate)
string text = "Bonjour le monde";
Language detected2 = translator.DetectLanguage(text,
new[] { Language.English, Language.French, Language.Spanish, Language.German });
// Translate to a specific language
string french = translator.Translate(text, Language.French);
string japanese = translator.Translate(text, Language.Japanese);
string portuguese = translator.Translate(text, Language.Portuguese);
Step 4: Batch Translation
Translate multiple texts efficiently:
using System.Text;
using LMKit.Model;
using LMKit.TextGeneration;
using LMKit.TextGeneration.Chat;
using LMKit.Translation;
LMKit.Licensing.LicenseManager.SetLicenseKey("");
Console.InputEncoding = Encoding.UTF8;
Console.OutputEncoding = Encoding.UTF8;
// ──────────────────────────────────────
// 1. Load a multilingual model
// ──────────────────────────────────────
Console.WriteLine("Loading model...");
using LM model = LM.LoadFromModelID("qwen3:4b",
downloadingProgress: (_, len, read) =>
{
if (len.HasValue) Console.Write($"\r Downloading: {(double)read / len.Value * 100:F1}% ");
return true;
},
loadingProgress: p => { Console.Write($"\r Loading: {p * 100:F0}% "); return true; });
Console.WriteLine("\n");
// ──────────────────────────────────────
// 2. Create translator with streaming
// ──────────────────────────────────────
var translator = new TextTranslation(model);
translator.AfterTextCompletion += (_, e) =>
{
if (e.SegmentType == TextSegmentType.UserVisible)
Console.Write(e.Text);
};
// ──────────────────────────────────────
// 3. Translation loop
// ──────────────────────────────────────
Console.WriteLine("Enter text to translate (or 'quit' to exit).");
Console.WriteLine("Target language defaults to English. Type 'lang:French' to change.\n");
Language targetLanguage = Language.English;
while (true)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write($"[→ {targetLanguage}] Text: ");
Console.ResetColor();
string? input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input) || input.Equals("quit", StringComparison.OrdinalIgnoreCase))
break;
// Allow changing target language
if (input.StartsWith("lang:", StringComparison.OrdinalIgnoreCase))
{
string langName = input.Substring(5).Trim();
if (Enum.TryParse<Language>(langName, ignoreCase: true, out Language parsed))
{
targetLanguage = parsed;
Console.WriteLine($" Target language set to {targetLanguage}\n");
}
else
{
Console.WriteLine($" Unknown language: {langName}\n");
}
continue;
}
// Detect source language
Language detected = translator.DetectLanguage(input);
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine($" Detected: {detected} ({translator.Confidence:P0})");
Console.ResetColor();
// Translate
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write(" Translation: ");
Console.ResetColor();
string result = translator.Translate(input, targetLanguage);
Console.WriteLine("\n");
}
string[] sourceTexts =
{
"Welcome to our product documentation.",
"Click the Settings icon to configure your account.",
"For support, contact our help desk at support@example.com."
};
Language[] targets = { Language.French, Language.Spanish, Language.German };
foreach (Language target in targets)
{
Console.WriteLine($"\n=== {target} ===");
foreach (string text in sourceTexts)
{
string translated = translator.Translate(text, target);
Console.WriteLine($" {translated}");
}
}
Step 5: Language Detection for Documents
Detect the language of files (PDFs, images with text) using attachments:
using LMKit.Data;
// Detect language from a PDF
var doc = new Attachment("contract.pdf");
Language docLanguage = translator.DetectLanguage(doc);
Console.WriteLine($"Document language: {docLanguage} ({translator.Confidence:P0})");
Supported Languages
LM-Kit.NET supports these languages through the Language enum:
| Language | Enum Value | Language | Enum Value |
|---|---|---|---|
| Arabic | Language.Arabic |
Japanese | Language.Japanese |
| Chinese (Simplified) | Language.ChineseSimplified |
Korean | Language.Korean |
| Chinese (Traditional) | Language.ChineseTraditional |
Portuguese | Language.Portuguese |
| Dutch | Language.Dutch |
Russian | Language.Russian |
| English | Language.English |
Spanish | Language.Spanish |
| French | Language.French |
Hindi | Language.Hindi |
| German | Language.German |
Italian | Language.Italian |
The actual language quality depends on the model. qwen3:4b excels at CJK languages. gemma3:4b works well across European languages.
Model Selection for Translation
| Model ID | VRAM | Multilingual Strength | Best For |
|---|---|---|---|
qwen3:4b |
~3.5 GB | Excellent (CJK + European) | General multilingual use (recommended) |
gemma3:4b |
~3.5 GB | Very good (European) | European language pairs |
qwen3:8b |
~6 GB | Excellent | Highest translation quality |
gemma3:12b |
~8 GB | Excellent | Complex, nuanced texts |
For most translation tasks, qwen3:4b offers the best balance of quality, speed, and language coverage.
Common Issues
| Problem | Cause | Fix |
|---|---|---|
| Wrong language detected | Short text or ambiguous content | Restrict detection to expected languages with the languages parameter |
| Translation is too literal | Model preserving source structure | Use a larger model (8B+) for more natural phrasing |
| Missing characters in output | Console encoding wrong | Ensure Console.OutputEncoding = Encoding.UTF8 is set |
| Slow translation for long texts | Full document processed at once | Split into paragraphs and translate individually |
| Mixed-language input confused | Text contains multiple languages | Translate sentence by sentence for mixed-language content |
Next Steps
- Load a Model and Generate Your First Response: model loading fundamentals if you are new to LM-Kit.NET.
- Classify and Extract Data from Documents: combine translation with document classification.
- Analyze Customer Sentiment at Scale: analyze sentiment in multilingual feedback.
- Samples: Text Translator: full translation demo.