feat(languages): expand speech catalog with Hungarian and more (#616)
Expose Hungarian and other high-demand Whisper languages in Settings/CLI, wire official VOSK models where Alphacephei ships them, keep CLI choices derived from SUPPORTED_LANGUAGES, and update the languages marketing page with honest per-engine support. Fixes #565 Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Jatin K Malik <jatinkrmalik@users.noreply.github.com>
This commit is contained in:
co-authored by
Cursor Agent
Jatin K Malik
parent
ca24264c85
commit
28bed4c1fd
+7
-18
@@ -8,6 +8,7 @@ import atexit
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from .utils.vosk_model_info import SUPPORTED_LANGUAGES
|
||||
from .version import __version__
|
||||
|
||||
# Configure logging
|
||||
@@ -20,6 +21,9 @@ logger = logging.getLogger(__name__)
|
||||
# Note: GTK-dependent modules (tray_indicator) are imported lazily after
|
||||
# dependency checking to provide better error messages for pip/pipx users
|
||||
|
||||
# Keep CLI --language choices in sync with the Settings catalog.
|
||||
LANGUAGE_CHOICES = tuple(SUPPORTED_LANGUAGES.keys())
|
||||
|
||||
|
||||
def _should_append_trailing_space() -> bool:
|
||||
"""Return whether completed transcriptions should get a trailing space.
|
||||
@@ -68,25 +72,10 @@ def parse_arguments():
|
||||
parser.add_argument(
|
||||
"--language",
|
||||
type=str,
|
||||
choices=[
|
||||
"auto",
|
||||
"en-us",
|
||||
"en-in",
|
||||
"hi",
|
||||
"es",
|
||||
"fr",
|
||||
"de",
|
||||
"it",
|
||||
"pt",
|
||||
"ru",
|
||||
"zh",
|
||||
"ja",
|
||||
"ko",
|
||||
"ar",
|
||||
],
|
||||
choices=LANGUAGE_CHOICES,
|
||||
help=(
|
||||
"Speech recognition language (auto for auto-detect, en-us, "
|
||||
"hi, es, fr, de, it, pt, ru, zh, etc.)"
|
||||
"Speech recognition language (auto for auto-detect, or a code "
|
||||
"from the Settings language catalog such as en-us, hu, ja, …)"
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# Language definitions with display names and Whisper/VOSK codes
|
||||
# Supported languages for speech recognition
|
||||
#
|
||||
# Whisper / whisper.cpp / remote_api use the catalog key (or the "whisper"
|
||||
# code for English-only model checks). VOSK uses per-language model zips from
|
||||
# VOSK_MODEL_INFO; set "vosk" to None when no official Alphacephei model exists.
|
||||
# Medium/large must cover every language present in small (see issue #550).
|
||||
SUPPORTED_LANGUAGES = {
|
||||
"auto": {
|
||||
"name": "Auto-detect",
|
||||
@@ -12,15 +17,50 @@ SUPPORTED_LANGUAGES = {
|
||||
"whisper": "en",
|
||||
"vosk": "vosk-model-small-en-us-0.15",
|
||||
},
|
||||
"hi": {
|
||||
"name": "Hindi",
|
||||
"whisper": "hi",
|
||||
"vosk": "vosk-model-small-hi-0.22",
|
||||
"en-in": {
|
||||
"name": "English (India)",
|
||||
"whisper": "en",
|
||||
"vosk": "vosk-model-small-en-in-0.4",
|
||||
},
|
||||
"es": {
|
||||
"name": "Spanish",
|
||||
"whisper": "es",
|
||||
"vosk": "vosk-model-small-es-0.42",
|
||||
"ar": {
|
||||
"name": "Arabic",
|
||||
"whisper": "ar",
|
||||
"vosk": "vosk-model-small-ar-0.3",
|
||||
},
|
||||
"bn": {
|
||||
"name": "Bengali",
|
||||
"whisper": "bn",
|
||||
"vosk": None,
|
||||
},
|
||||
"ca": {
|
||||
"name": "Catalan",
|
||||
"whisper": "ca",
|
||||
"vosk": "vosk-model-small-ca-0.4",
|
||||
},
|
||||
"zh": {
|
||||
"name": "Chinese",
|
||||
"whisper": "zh",
|
||||
"vosk": "vosk-model-small-cn-0.22",
|
||||
},
|
||||
"cs": {
|
||||
"name": "Czech",
|
||||
"whisper": "cs",
|
||||
"vosk": "vosk-model-small-cs-0.4-rhasspy",
|
||||
},
|
||||
"da": {
|
||||
"name": "Danish",
|
||||
"whisper": "da",
|
||||
"vosk": None,
|
||||
},
|
||||
"nl": {
|
||||
"name": "Dutch",
|
||||
"whisper": "nl",
|
||||
"vosk": "vosk-model-small-nl-0.22",
|
||||
},
|
||||
"fi": {
|
||||
"name": "Finnish",
|
||||
"whisper": "fi",
|
||||
"vosk": None,
|
||||
},
|
||||
"fr": {
|
||||
"name": "French",
|
||||
@@ -32,30 +72,117 @@ SUPPORTED_LANGUAGES = {
|
||||
"whisper": "de",
|
||||
"vosk": "vosk-model-small-de-0.15",
|
||||
},
|
||||
"el": {
|
||||
"name": "Greek",
|
||||
"whisper": "el",
|
||||
"vosk": None,
|
||||
},
|
||||
"he": {
|
||||
"name": "Hebrew",
|
||||
"whisper": "he",
|
||||
"vosk": None,
|
||||
},
|
||||
"hi": {
|
||||
"name": "Hindi",
|
||||
"whisper": "hi",
|
||||
"vosk": "vosk-model-small-hi-0.22",
|
||||
},
|
||||
"hu": {
|
||||
"name": "Hungarian",
|
||||
"whisper": "hu",
|
||||
"vosk": None,
|
||||
},
|
||||
"id": {
|
||||
"name": "Indonesian",
|
||||
"whisper": "id",
|
||||
"vosk": None,
|
||||
},
|
||||
"it": {
|
||||
"name": "Italian",
|
||||
"whisper": "it",
|
||||
"vosk": "vosk-model-small-it-0.22",
|
||||
},
|
||||
"ja": {
|
||||
"name": "Japanese",
|
||||
"whisper": "ja",
|
||||
"vosk": "vosk-model-small-ja-0.22",
|
||||
},
|
||||
"ko": {
|
||||
"name": "Korean",
|
||||
"whisper": "ko",
|
||||
"vosk": "vosk-model-small-ko-0.22",
|
||||
},
|
||||
"no": {
|
||||
"name": "Norwegian",
|
||||
"whisper": "no",
|
||||
"vosk": None,
|
||||
},
|
||||
"fa": {
|
||||
"name": "Persian",
|
||||
"whisper": "fa",
|
||||
"vosk": "vosk-model-small-fa-0.42",
|
||||
},
|
||||
"pl": {
|
||||
"name": "Polish",
|
||||
"whisper": "pl",
|
||||
"vosk": "vosk-model-small-pl-0.22",
|
||||
},
|
||||
"pt": {
|
||||
"name": "Portuguese",
|
||||
"whisper": "pt",
|
||||
"vosk": "vosk-model-small-pt-0.3",
|
||||
},
|
||||
"ro": {
|
||||
"name": "Romanian",
|
||||
"whisper": "ro",
|
||||
"vosk": None,
|
||||
},
|
||||
"ru": {
|
||||
"name": "Russian",
|
||||
"whisper": "ru",
|
||||
"vosk": "vosk-model-small-ru-0.22",
|
||||
},
|
||||
"zh": {
|
||||
"name": "Chinese",
|
||||
"whisper": "zh",
|
||||
"vosk": "vosk-model-small-cn-0.22",
|
||||
"es": {
|
||||
"name": "Spanish",
|
||||
"whisper": "es",
|
||||
"vosk": "vosk-model-small-es-0.42",
|
||||
},
|
||||
"sv": {
|
||||
"name": "Swedish",
|
||||
"whisper": "sv",
|
||||
"vosk": "vosk-model-small-sv-rhasspy-0.15",
|
||||
},
|
||||
"ta": {
|
||||
"name": "Tamil",
|
||||
"whisper": "ta",
|
||||
"vosk": None,
|
||||
},
|
||||
"th": {
|
||||
"name": "Thai",
|
||||
"whisper": "th",
|
||||
"vosk": None,
|
||||
},
|
||||
"tr": {
|
||||
"name": "Turkish",
|
||||
"whisper": "tr",
|
||||
"vosk": "vosk-model-small-tr-0.3",
|
||||
},
|
||||
"uk": {
|
||||
"name": "Ukrainian",
|
||||
"whisper": "uk",
|
||||
"vosk": "vosk-model-small-uk-v3-small",
|
||||
},
|
||||
"vi": {
|
||||
"name": "Vietnamese",
|
||||
"whisper": "vi",
|
||||
"vosk": "vosk-model-small-vn-0.4",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# VOSK model metadata for display
|
||||
# VOSK model metadata for display and download path resolution.
|
||||
# When Alphacephei only ships a small model, medium/large point at that same
|
||||
# zip so size selection never resolves to None (issue #550).
|
||||
VOSK_MODEL_INFO = {
|
||||
"small": {
|
||||
"size_mb": 40,
|
||||
@@ -63,14 +190,26 @@ VOSK_MODEL_INFO = {
|
||||
"languages": {
|
||||
"en-us": "vosk-model-small-en-us-0.15",
|
||||
"en-in": "vosk-model-small-en-in-0.4",
|
||||
"hi": "vosk-model-small-hi-0.22",
|
||||
"es": "vosk-model-small-es-0.42",
|
||||
"ar": "vosk-model-small-ar-0.3",
|
||||
"ca": "vosk-model-small-ca-0.4",
|
||||
"zh": "vosk-model-small-cn-0.22",
|
||||
"cs": "vosk-model-small-cs-0.4-rhasspy",
|
||||
"nl": "vosk-model-small-nl-0.22",
|
||||
"fr": "vosk-model-small-fr-0.22",
|
||||
"de": "vosk-model-small-de-0.15",
|
||||
"hi": "vosk-model-small-hi-0.22",
|
||||
"it": "vosk-model-small-it-0.22",
|
||||
"ja": "vosk-model-small-ja-0.22",
|
||||
"ko": "vosk-model-small-ko-0.22",
|
||||
"fa": "vosk-model-small-fa-0.42",
|
||||
"pl": "vosk-model-small-pl-0.22",
|
||||
"pt": "vosk-model-small-pt-0.3",
|
||||
"ru": "vosk-model-small-ru-0.22",
|
||||
"zh": "vosk-model-small-cn-0.22",
|
||||
"es": "vosk-model-small-es-0.42",
|
||||
"sv": "vosk-model-small-sv-rhasspy-0.15",
|
||||
"tr": "vosk-model-small-tr-0.3",
|
||||
"uk": "vosk-model-small-uk-v3-small",
|
||||
"vi": "vosk-model-small-vn-0.4",
|
||||
},
|
||||
},
|
||||
"medium": {
|
||||
@@ -79,14 +218,26 @@ VOSK_MODEL_INFO = {
|
||||
"languages": {
|
||||
"en-us": "vosk-model-en-us-0.22",
|
||||
"en-in": "vosk-model-en-in-0.5",
|
||||
"ar": "vosk-model-ar-0.22-linto-1.1.0",
|
||||
"ca": "vosk-model-small-ca-0.4",
|
||||
"zh": "vosk-model-cn-0.22",
|
||||
"cs": "vosk-model-small-cs-0.4-rhasspy",
|
||||
"nl": "vosk-model-nl-spraakherkenning-0.6",
|
||||
"fr": "vosk-model-fr-0.22",
|
||||
"de": "vosk-model-de-0.21",
|
||||
"it": "vosk-model-it-0.22",
|
||||
"ru": "vosk-model-ru-0.22",
|
||||
"hi": "vosk-model-hi-0.22",
|
||||
"es": "vosk-model-es-0.42",
|
||||
"it": "vosk-model-it-0.22",
|
||||
"ja": "vosk-model-ja-0.22",
|
||||
"ko": "vosk-model-small-ko-0.22",
|
||||
"fa": "vosk-model-fa-0.42",
|
||||
"pl": "vosk-model-small-pl-0.22",
|
||||
"pt": "vosk-model-pt-0.4",
|
||||
"zh": "vosk-model-cn-0.22",
|
||||
"ru": "vosk-model-ru-0.22",
|
||||
"es": "vosk-model-es-0.42",
|
||||
"sv": "vosk-model-small-sv-rhasspy-0.15",
|
||||
"tr": "vosk-model-small-tr-0.3",
|
||||
"uk": "vosk-model-uk-v3",
|
||||
"vi": "vosk-model-vn-0.4",
|
||||
},
|
||||
},
|
||||
"large": {
|
||||
@@ -95,14 +246,26 @@ VOSK_MODEL_INFO = {
|
||||
"languages": {
|
||||
"en-us": "vosk-model-en-us-0.22",
|
||||
"en-in": "vosk-model-en-in-0.5",
|
||||
"ar": "vosk-model-ar-0.22-linto-1.1.0",
|
||||
"ca": "vosk-model-small-ca-0.4",
|
||||
"zh": "vosk-model-cn-0.22",
|
||||
"cs": "vosk-model-small-cs-0.4-rhasspy",
|
||||
"nl": "vosk-model-nl-spraakherkenning-0.6",
|
||||
"fr": "vosk-model-fr-0.22",
|
||||
"de": "vosk-model-de-0.21",
|
||||
"it": "vosk-model-it-0.22",
|
||||
"ru": "vosk-model-ru-0.22",
|
||||
"hi": "vosk-model-hi-0.22",
|
||||
"es": "vosk-model-es-0.42",
|
||||
"it": "vosk-model-it-0.22",
|
||||
"ja": "vosk-model-ja-0.22",
|
||||
"ko": "vosk-model-small-ko-0.22",
|
||||
"fa": "vosk-model-fa-0.42",
|
||||
"pl": "vosk-model-small-pl-0.22",
|
||||
"pt": "vosk-model-pt-0.4",
|
||||
"zh": "vosk-model-cn-0.22",
|
||||
"ru": "vosk-model-ru-0.22",
|
||||
"es": "vosk-model-es-0.42",
|
||||
"sv": "vosk-model-small-sv-rhasspy-0.15",
|
||||
"tr": "vosk-model-small-tr-0.3",
|
||||
"uk": "vosk-model-uk-v3",
|
||||
"vi": "vosk-model-vn-0.4",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
+8
-17
@@ -90,23 +90,14 @@ class TestMainModule(unittest.TestCase):
|
||||
self.assertEqual(args.engine, "whisper")
|
||||
|
||||
def test_parse_arguments_language_choices(self):
|
||||
"""Test that language only accepts valid choices."""
|
||||
for lang in [
|
||||
"auto",
|
||||
"en-us",
|
||||
"en-in",
|
||||
"hi",
|
||||
"es",
|
||||
"fr",
|
||||
"de",
|
||||
"it",
|
||||
"pt",
|
||||
"ru",
|
||||
"zh",
|
||||
"ja",
|
||||
"ko",
|
||||
"ar",
|
||||
]:
|
||||
"""Test that language only accepts valid choices from the catalog."""
|
||||
from vocalinux.main import LANGUAGE_CHOICES
|
||||
from vocalinux.utils.vosk_model_info import SUPPORTED_LANGUAGES
|
||||
|
||||
self.assertEqual(LANGUAGE_CHOICES, tuple(SUPPORTED_LANGUAGES.keys()))
|
||||
# Spot-check newly exposed languages (issue #565 and catalog expansion).
|
||||
for lang in ["auto", "en-us", "hu", "ja", "ko", "ar", "nl", "pl", "uk"]:
|
||||
self.assertIn(lang, LANGUAGE_CHOICES)
|
||||
with patch("sys.argv", ["vocalinux", "--language", lang]):
|
||||
args = parse_arguments()
|
||||
self.assertEqual(args.language, lang)
|
||||
|
||||
@@ -275,6 +275,36 @@ class TestSpeechRecognition(unittest.TestCase):
|
||||
"otherwise initialization crashes with a NoneType path error.",
|
||||
)
|
||||
|
||||
def test_supported_languages_vosk_entries_match_model_tables(self):
|
||||
"""Every catalog language with a VOSK model must appear in size tables."""
|
||||
from vocalinux.utils.vosk_model_info import SUPPORTED_LANGUAGES
|
||||
|
||||
for lang_code, lang_info in SUPPORTED_LANGUAGES.items():
|
||||
vosk_model = lang_info.get("vosk")
|
||||
if not vosk_model:
|
||||
continue
|
||||
self.assertEqual(
|
||||
VOSK_MODEL_INFO["small"]["languages"].get(lang_code),
|
||||
vosk_model,
|
||||
f"SUPPORTED_LANGUAGES['{lang_code}']['vosk'] must match "
|
||||
f"VOSK_MODEL_INFO['small']['languages']['{lang_code}']",
|
||||
)
|
||||
for size in ("medium", "large"):
|
||||
self.assertIn(
|
||||
lang_code,
|
||||
VOSK_MODEL_INFO[size]["languages"],
|
||||
f"VOSK language '{lang_code}' missing from '{size}' table",
|
||||
)
|
||||
|
||||
def test_hungarian_is_whisper_only_in_catalog(self):
|
||||
"""Hungarian (issue #565) is exposed for Whisper engines, not VOSK."""
|
||||
from vocalinux.utils.vosk_model_info import SUPPORTED_LANGUAGES
|
||||
|
||||
hu = SUPPORTED_LANGUAGES["hu"]
|
||||
self.assertEqual(hu["whisper"], "hu")
|
||||
self.assertIsNone(hu["vosk"])
|
||||
self.assertNotIn("hu", VOSK_MODEL_INFO["small"]["languages"])
|
||||
|
||||
def test_vosk_init_italian_medium_model_resolves_correctly(self):
|
||||
"""Selecting Italian + the 'medium' VOSK model must not crash (issue #550)."""
|
||||
manager = SpeechRecognitionManager(engine="vosk", language="it", model_size="medium")
|
||||
|
||||
+256
-64
@@ -4,6 +4,9 @@ import { CheckCircle2, ChevronRight, Globe, Languages, Mic } from "lucide-react"
|
||||
import { SeoSubpageShell } from "@/components/seo-subpage-shell";
|
||||
import { absoluteUrl, buildPageMetadata } from "@/lib/seo";
|
||||
|
||||
const WHISPER_ENGINES = ["whisper.cpp", "Whisper"] as const;
|
||||
const ALL_ENGINES = ["whisper.cpp", "Whisper", "VOSK"] as const;
|
||||
|
||||
const supportedLanguages = [
|
||||
{
|
||||
code: "en",
|
||||
@@ -11,62 +14,39 @@ const supportedLanguages = [
|
||||
nativeName: "English",
|
||||
flag: "🇺🇸",
|
||||
description: "Full support across all engines (whisper.cpp, Whisper, VOSK)",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "es",
|
||||
name: "Spanish",
|
||||
nativeName: "Español",
|
||||
flag: "🇪🇸",
|
||||
description: "Complete Spanish language support for dictation",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
code: "en-in",
|
||||
name: "English (India)",
|
||||
nativeName: "English (India)",
|
||||
flag: "🇮🇳",
|
||||
description: "Indian English dictation with a dedicated VOSK model",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "fr",
|
||||
name: "French",
|
||||
nativeName: "Français",
|
||||
flag: "🇫🇷",
|
||||
description: "French language voice typing and transcription",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
code: "ar",
|
||||
name: "Arabic",
|
||||
nativeName: "العربية",
|
||||
flag: "🇸🇦",
|
||||
description: "Arabic speech recognition across Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "de",
|
||||
name: "German",
|
||||
nativeName: "Deutsch",
|
||||
flag: "🇩🇪",
|
||||
description: "German dictation with high accuracy",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
code: "bn",
|
||||
name: "Bengali",
|
||||
nativeName: "বাংলা",
|
||||
flag: "🇧🇩",
|
||||
description: "Bengali dictation with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "it",
|
||||
name: "Italian",
|
||||
nativeName: "Italiano",
|
||||
flag: "🇮🇹",
|
||||
description: "Italian voice recognition and text dictation",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
},
|
||||
{
|
||||
code: "pt",
|
||||
name: "Portuguese",
|
||||
nativeName: "Português",
|
||||
flag: "🇧🇷",
|
||||
description: "Brazilian and European Portuguese support",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
},
|
||||
{
|
||||
code: "ru",
|
||||
name: "Russian",
|
||||
nativeName: "Русский",
|
||||
flag: "🇷🇺",
|
||||
description: "Russian language speech-to-text transcription",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
code: "ca",
|
||||
name: "Catalan",
|
||||
nativeName: "Català",
|
||||
flag: "🇦🇩",
|
||||
description: "Catalan voice typing with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "zh",
|
||||
@@ -74,8 +54,71 @@ const supportedLanguages = [
|
||||
nativeName: "中文",
|
||||
flag: "🇨🇳",
|
||||
description: "Mandarin Chinese voice dictation support",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "cs",
|
||||
name: "Czech",
|
||||
nativeName: "Čeština",
|
||||
flag: "🇨🇿",
|
||||
description: "Czech dictation with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "da",
|
||||
name: "Danish",
|
||||
nativeName: "Dansk",
|
||||
flag: "🇩🇰",
|
||||
description: "Danish speech-to-text with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "nl",
|
||||
name: "Dutch",
|
||||
nativeName: "Nederlands",
|
||||
flag: "🇳🇱",
|
||||
description: "Dutch voice recognition across Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "fi",
|
||||
name: "Finnish",
|
||||
nativeName: "Suomi",
|
||||
flag: "🇫🇮",
|
||||
description: "Finnish dictation with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "fr",
|
||||
name: "French",
|
||||
nativeName: "Français",
|
||||
flag: "🇫🇷",
|
||||
description: "French language voice typing and transcription",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "de",
|
||||
name: "German",
|
||||
nativeName: "Deutsch",
|
||||
flag: "🇩🇪",
|
||||
description: "German dictation with high accuracy",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "el",
|
||||
name: "Greek",
|
||||
nativeName: "Ελληνικά",
|
||||
flag: "🇬🇷",
|
||||
description: "Greek speech recognition with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "he",
|
||||
name: "Hebrew",
|
||||
nativeName: "עברית",
|
||||
flag: "🇮🇱",
|
||||
description: "Hebrew dictation with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "hi",
|
||||
@@ -83,11 +126,156 @@ const supportedLanguages = [
|
||||
nativeName: "हिन्दी",
|
||||
flag: "🇮🇳",
|
||||
description: "Hindi language voice typing and transcription",
|
||||
engines: ["whisper.cpp", "Whisper", "VOSK"],
|
||||
modelSizes: ["tiny", "base", "small", "medium", "large"],
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "hu",
|
||||
name: "Hungarian",
|
||||
nativeName: "Magyar",
|
||||
flag: "🇭🇺",
|
||||
description: "Hungarian dictation with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "id",
|
||||
name: "Indonesian",
|
||||
nativeName: "Bahasa Indonesia",
|
||||
flag: "🇮🇩",
|
||||
description: "Indonesian voice typing with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "it",
|
||||
name: "Italian",
|
||||
nativeName: "Italiano",
|
||||
flag: "🇮🇹",
|
||||
description: "Italian voice recognition and text dictation",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "ja",
|
||||
name: "Japanese",
|
||||
nativeName: "日本語",
|
||||
flag: "🇯🇵",
|
||||
description: "Japanese speech-to-text across Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "ko",
|
||||
name: "Korean",
|
||||
nativeName: "한국어",
|
||||
flag: "🇰🇷",
|
||||
description: "Korean dictation with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "no",
|
||||
name: "Norwegian",
|
||||
nativeName: "Norsk",
|
||||
flag: "🇳🇴",
|
||||
description: "Norwegian speech recognition with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "fa",
|
||||
name: "Persian",
|
||||
nativeName: "فارسی",
|
||||
flag: "🇮🇷",
|
||||
description: "Persian (Farsi) dictation with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "pl",
|
||||
name: "Polish",
|
||||
nativeName: "Polski",
|
||||
flag: "🇵🇱",
|
||||
description: "Polish voice typing with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "pt",
|
||||
name: "Portuguese",
|
||||
nativeName: "Português",
|
||||
flag: "🇧🇷",
|
||||
description: "Brazilian and European Portuguese support",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "ro",
|
||||
name: "Romanian",
|
||||
nativeName: "Română",
|
||||
flag: "🇷🇴",
|
||||
description: "Romanian dictation with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "ru",
|
||||
name: "Russian",
|
||||
nativeName: "Русский",
|
||||
flag: "🇷🇺",
|
||||
description: "Russian language speech-to-text transcription",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "es",
|
||||
name: "Spanish",
|
||||
nativeName: "Español",
|
||||
flag: "🇪🇸",
|
||||
description: "Complete Spanish language support for dictation",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "sv",
|
||||
name: "Swedish",
|
||||
nativeName: "Svenska",
|
||||
flag: "🇸🇪",
|
||||
description: "Swedish voice recognition with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "ta",
|
||||
name: "Tamil",
|
||||
nativeName: "தமிழ்",
|
||||
flag: "🇮🇳",
|
||||
description: "Tamil dictation with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "th",
|
||||
name: "Thai",
|
||||
nativeName: "ไทย",
|
||||
flag: "🇹🇭",
|
||||
description: "Thai speech-to-text with multilingual Whisper models",
|
||||
engines: [...WHISPER_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "tr",
|
||||
name: "Turkish",
|
||||
nativeName: "Türkçe",
|
||||
flag: "🇹🇷",
|
||||
description: "Turkish dictation with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "uk",
|
||||
name: "Ukrainian",
|
||||
nativeName: "Українська",
|
||||
flag: "🇺🇦",
|
||||
description: "Ukrainian voice typing with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
{
|
||||
code: "vi",
|
||||
name: "Vietnamese",
|
||||
nativeName: "Tiếng Việt",
|
||||
flag: "🇻🇳",
|
||||
description: "Vietnamese speech recognition with Whisper and VOSK",
|
||||
engines: [...ALL_ENGINES],
|
||||
},
|
||||
];
|
||||
|
||||
const languageCount = supportedLanguages.length;
|
||||
|
||||
const features = [
|
||||
{
|
||||
title: "Automatic Language Detection",
|
||||
@@ -96,9 +284,9 @@ const features = [
|
||||
icon: Globe,
|
||||
},
|
||||
{
|
||||
title: "Multi-Engine Support",
|
||||
title: "Engine-Aware Catalog",
|
||||
description:
|
||||
"All supported languages work across whisper.cpp, OpenAI Whisper, and VOSK engines.",
|
||||
"Whisper engines cover the full language list. VOSK appears only where an official model exists.",
|
||||
icon: Mic,
|
||||
},
|
||||
{
|
||||
@@ -110,15 +298,19 @@ const features = [
|
||||
];
|
||||
|
||||
export const metadata: Metadata = buildPageMetadata({
|
||||
title: "Multilingual Voice Dictation - Spanish, French, German, & More | Vocalinux",
|
||||
title: "Multilingual Voice Dictation - 30+ Languages | Vocalinux",
|
||||
description:
|
||||
"Dictate in 9+ languages including Spanish, French, German, Italian, Portuguese, Russian, Chinese, and Hindi. Free offline multilingual voice typing for Linux.",
|
||||
"Dictate in 30+ languages including Spanish, French, German, Hungarian, Japanese, Korean, Arabic, and more. Free offline multilingual voice typing for Linux.",
|
||||
path: "/languages",
|
||||
keywords: [
|
||||
"multilingual voice dictation",
|
||||
"Spanish voice typing",
|
||||
"French speech to text",
|
||||
"German dictation software",
|
||||
"Hungarian voice recognition",
|
||||
"Japanese speech to text",
|
||||
"Korean voice typing",
|
||||
"Arabic dictation",
|
||||
"Italian voice recognition",
|
||||
"Portuguese voice typing",
|
||||
"Russian speech recognition",
|
||||
@@ -132,10 +324,10 @@ export default function LanguagesPage() {
|
||||
const articleJsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
headline: "Multilingual Voice Dictation for Linux - 9+ Languages Supported",
|
||||
headline: `Multilingual Voice Dictation for Linux - ${languageCount}+ Languages Supported`,
|
||||
description:
|
||||
"Complete guide to Vocalinux multilingual voice dictation. Dictate in Spanish, French, German, Italian, Portuguese, Russian, Chinese, Hindi, and more.",
|
||||
dateModified: "2026-02-22",
|
||||
"Complete guide to Vocalinux multilingual voice dictation. Dictate in Spanish, French, German, Hungarian, Japanese, Korean, Arabic, Hindi, and more.",
|
||||
dateModified: "2026-07-29",
|
||||
author: {
|
||||
"@type": "Person",
|
||||
name: "Jatin K Malik",
|
||||
@@ -162,14 +354,14 @@ export default function LanguagesPage() {
|
||||
<section>
|
||||
<p className="subpage-kicker">
|
||||
<Languages className="h-4 w-4" />
|
||||
9+ Languages
|
||||
{languageCount}+ Languages
|
||||
</p>
|
||||
<h1 className="mb-5 font-display text-4xl font-semibold tracking-tight sm:text-5xl">
|
||||
Multilingual Voice Dictation for Linux
|
||||
</h1>
|
||||
<p className="mb-8 max-w-4xl text-lg text-muted-foreground">
|
||||
Dictate in your native language. Vocalinux supports 9+ languages with full offline
|
||||
processing - no cloud required, no data leaves your machine.
|
||||
Dictate in your native language. Vocalinux lists {languageCount} languages in Settings,
|
||||
and whisper.cpp / Whisper can auto-detect many more - all offline, with no cloud upload.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -232,7 +424,7 @@ export default function LanguagesPage() {
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-primary" />
|
||||
Use "Auto" for automatic language detection (whisper.cpp/Whisper)
|
||||
Use "Auto" for automatic language detection (whisper.cpp/Whisper)
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-primary" />
|
||||
@@ -249,7 +441,7 @@ export default function LanguagesPage() {
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-primary" />
|
||||
"tiny" model works for all supported languages
|
||||
Use a Standard multilingual whisper.cpp model for non-English dictation
|
||||
</li>
|
||||
<li className="flex items-start gap-2">
|
||||
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-primary" />
|
||||
|
||||
Reference in New Issue
Block a user