diff --git a/.gitignore b/.gitignore index 0be8af1..e0d8944 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ manifest.ini *.py[co] *.nvda-addon .sconsign.dblite +.agent/ +.venv/ +.ruff_cache/ /[0-9]*.[0-9]*.[0-9]*.json diff --git a/addon/doc/es/readme.md b/addon/doc/es/readme.md new file mode 100644 index 0000000..e313f1a --- /dev/null +++ b/addon/doc/es/readme.md @@ -0,0 +1,99 @@ +# Native Speech Generation para NVDA + +**Autor:** Muhammad Gagah [muha.aku@gmail.com](mailto:muha.aku@gmail.com) + +Native Speech Generation es un complemento para NVDA que integra **Google Gemini AI** para generar voz de alta calidad y sonido natural directamente en NVDA. Proporciona una interfaz limpia y totalmente accesible para convertir texto en audio, admitiendo tanto **narración de un solo hablante** como **diálogos dinámicos de varios hablantes**. + +Este complemento está diseñado para flujos de trabajo fluidos, interacción centrada en la accesibilidad y un control de voz flexible adecuado para narración, diálogos y producción de contenido de audio. + +--- + +## Características + +### Generación de voz de alta calidad +* **Elija entre:** + * **Gemini Flash:** Calidad estándar, generación rápida, baja latencia. + * **Gemini Pro:** Premium, voces más realistas (modelo de pago). + +### Modos de hablante único y múltiple +* **Narración de hablante único** para conversión de texto a voz estándar. +* **Modo multihablante (2 hablantes)** para diálogos con voces distintas. + +### Control de voz avanzado +* **Asignación de nombres a los hablantes:** Asigne nombres personalizados (ej. *Juan*, *María*) en el modo multihablante. La IA asigna automáticamente las voces según los nombres en el guion. +* **Instrucciones de estilo:** Proporcione indicaciones como *"Habla en un tono alegre"* o *"Narra con calma"* para guiar el habla. +* **Control de temperatura:** Ajuste la variación y creatividad de la salida: + * Valores bajos → voz más estable y predecible. + * Valores altos → voz más expresiva y variada. + +--- + +## Requisitos +* NVDA (se recomienda la versión más reciente). +* Conexión a internet activa. +* Una **clave de API de Google Gemini** válida. + +--- + +## Instalación +1. Descargue el paquete desde la [página de versiones (Releases)](https://github.com/MuhammadGagah/native-speech-generation/releases). +2. Instálelo como cualquier complemento de NVDA. +3. Reinicie NVDA cuando se le solicite. + +--- + +## Configuración de la clave de API (Requerido) +1. Cree una clave en [Google AI Studio](https://aistudio.google.com/apikey). +2. Vaya a: **Menú NVDA → Herramientas → Native Speech Generation**. +3. Haga clic en **"Configuración de clave API"**. +4. Pegue su clave en el campo **GEMINI API Key**. +5. Haga clic en **Aceptar**. + +--- + +## Cómo usar +Abra el diálogo usando: +* **NVDA+Control+Mayús+G**, o +* **Menú NVDA → Herramientas → Native Speech Generation** + +### Elementos de la interfaz +* **Texto a convertir:** Ingrese o pegue su texto. +* **Instrucciones de estilo:** (Opcional) Guía para el tono o emoción. +* **Seleccionar modelo:** Flash o Pro. +* **Modo de hablante:** Único o Multihablante (2). + +--- + +## Generación de voz + +### Modo de hablante único +1. Seleccione **Hablante único**. +2. Elija una voz, ingrese el texto y haga clic en **Generar voz**. + +### Modo multihablante +1. Seleccione **Multihablante (2)**. +2. Asigne un nombre y voz a cada hablante. +3. Formatee el texto así: + `Alicia: Hola Roberto, ¿cómo estás?` + `Roberto: ¡Muy bien! El clima es genial.` + +--- + +## Hablar con IA (Modo en vivo) +1. Haga clic en **Hablar con IA**. +2. **Iniciar conversación:** Comience a hablar por el micrófono. +3. **Conexión con Google Search:** Marque esta casilla para información en tiempo real. + +--- + +## Gestos de entrada +Personalizables en: **Menú NVDA → Preferencias → Gestos de entrada**. +* Predeterminado: **NVDA+Control+Mayús+G** + +--- + +## Contribuciones +* Reporte errores en la sección de **Issues**. +* Envíe mejoras mediante **Pull Requests**. + +**Contacto:** [muha.aku@gmail.com](mailto:muha.aku@gmail.com) | [GitHub](https://github.com/MuhammadGagah) diff --git a/addon/doc/id/readme.md b/addon/doc/id/readme.md index 0b9cc42..a525452 100644 --- a/addon/doc/id/readme.md +++ b/addon/doc/id/readme.md @@ -56,6 +56,9 @@ Add-on ini dirancang untuk alur kerja yang lancar, interaksi yang mengutamakan a * **Grounding dengan Pencarian Google**: Mengaktifkan AI untuk mengakses informasi real-time dari web selama obrolan Anda. * **Dapat Diinterupsi**: Anda dapat memotong pembicaraan AI kapan saja dengan berbicara atau menekan tombol "Hentikan Percakapan". * **Dapat Disesuaikan**: Menggunakan suara dan instruksi gaya yang Anda pilih. +* **Memori Sesi (Opsional)**: Menyimpan konteks percakapan sementara selama sesi Bicara dengan AI aktif agar respons lanjutan lebih koheren. +* **Kontrol Hapus Memori**: Menghapus memori sesi sementara sebelum percakapan dimulai (atau setelah percakapan dihentikan). +* **Streaming Lebih Stabil**: Perbaikan reconnect (backoff + retry) dan adaptive audio buffering agar lebih tahan terhadap jaringan yang tidak stabil. --- @@ -157,6 +160,8 @@ Rasakan percakapan suara dua arah yang alami dengan Gemini. * **Hentikan Percakapan**: Mengakhiri sesi. * **Grounding dengan Google Search**: Centang kotak ini untuk mengizinkan Gemini menelusuri web guna mencari jawaban (misalnya, berita terkini, cuaca). * *Catatan: Kotak centang ini disembunyikan saat percakapan sedang aktif. Hentikan percakapan untuk mengubahnya.* + * **Gunakan memori sesi**: Menyimpan memori sementara hanya untuk sesi percakapan saat ini. + * **Hapus memori sekarang**: Menghapus memori sementara sebelum memulai (atau setelah menghentikan) percakapan. * **Tombol Mikrofon**: Bisukan/Bunyikan mikrofon Anda. * **Volume**: Sesuaikan volume pemutaran AI. diff --git a/addon/globalPlugins/NativeSpeechGeneration/__init__.py b/addon/globalPlugins/NativeSpeechGeneration/__init__.py index 80dab8f..7207920 100644 --- a/addon/globalPlugins/NativeSpeechGeneration/__init__.py +++ b/addon/globalPlugins/NativeSpeechGeneration/__init__.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- import os -import sys import wx import addonHandler import globalPluginHandler @@ -23,11 +22,6 @@ def _(msg: str) -> str: # Initialization & Dependency Management pkgDir = os.path.dirname(os.path.abspath(__file__)) -# Ensure globalPlugins is in path -gpDir = os.path.dirname(pkgDir) -if gpDir not in sys.path: - sys.path.insert(0, gpDir) - # Libs setup try: from . import lib_updater @@ -53,8 +47,6 @@ def runCheck() -> None: wx.CallAfter(runCheck) else: - if libDir not in sys.path: - sys.path.insert(0, libDir) LIBS_AVAILABLE = True if not LIBS_AVAILABLE: @@ -74,7 +66,8 @@ def script_openDialog(self, gesture: Any) -> None: wx.CallAfter( wx.MessageBox, _( - "Native Speech Generation is installing dependencies. Please restart NVDA for the changes to take effect.", + "Native Speech Generation is installing dependencies. " + "Please restart NVDA for the changes to take effect.", ), # Translators: Title of the information dialog recommending a restart. _("Restart Required"), diff --git a/addon/globalPlugins/NativeSpeechGeneration/core/gemini_imports.py b/addon/globalPlugins/NativeSpeechGeneration/core/gemini_imports.py index 508e56a..bfae639 100644 --- a/addon/globalPlugins/NativeSpeechGeneration/core/gemini_imports.py +++ b/addon/globalPlugins/NativeSpeechGeneration/core/gemini_imports.py @@ -1,43 +1,36 @@ # -*- coding: utf-8 -*- -import sys -import platform +import os + from logHandler import log -GENAI_AVAILABLE = False -genai = None -types = None - -__all__ = ["genai", "types", "GENAI_AVAILABLE"] - -try: - # Dependency Conflict Resolution (Scoped / Safe Mode) - conflictingLibs = ["typing_extensions", "pydantic", "pydantic_core", "annotated_types"] - originalModules = {} - - for lib in conflictingLibs: - if lib in sys.modules: - originalModules[lib] = sys.modules[lib] - del sys.modules[lib] - try: - from google import genai - from google.genai import types - - GENAI_AVAILABLE = True - log.info("google-genai loaded successfully via core.gemini_imports") - finally: - # Restore original modules to avoid breaking other add-ons - for lib, module in originalModules.items(): - sys.modules[lib] = module -except Exception as e: - genai = None - types = None - GENAI_AVAILABLE = False - - errMsg = ( - f"Google GenAI Import Error:\n{e}\n\n" - f"Python: {sys.version}\n" - f"Arch: {platform.architecture()}\n" - f"Path: {sys.path[:3]}..." - ) - log.warning("google-genai not available", exc_info=True) - log.error(errMsg) +from .vendor_loader import load_runtime, runtime_scope + +_CORE_DIR = os.path.dirname(os.path.abspath(__file__)) +_PKG_DIR = os.path.dirname(_CORE_DIR) +_LIB_DIR = os.path.join(_PKG_DIR, "lib") +_RUNTIME = load_runtime(_LIB_DIR) + +genai = _RUNTIME.genai +types = _RUNTIME.types +pyaudio = _RUNTIME.pyaudio + +GENAI_AVAILABLE = _RUNTIME.genaiAvailable +PYAUDIO_AVAILABLE = _RUNTIME.pyaudioAvailable + +__all__ = [ + "genai", + "types", + "pyaudio", + "GENAI_AVAILABLE", + "PYAUDIO_AVAILABLE", + "getRuntimeScope", +] + +if not GENAI_AVAILABLE: + log.warning("google-genai not available via isolated vendor loader") +if not PYAUDIO_AVAILABLE: + log.warning("PyAudio not available via isolated vendor loader") + + +def getRuntimeScope(): + return runtime_scope(_RUNTIME) diff --git a/addon/globalPlugins/NativeSpeechGeneration/core/vendor_loader.py b/addon/globalPlugins/NativeSpeechGeneration/core/vendor_loader.py new file mode 100644 index 0000000..04ed903 --- /dev/null +++ b/addon/globalPlugins/NativeSpeechGeneration/core/vendor_loader.py @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +import contextlib +import importlib +import os +import sys +import threading +from dataclasses import dataclass +from types import ModuleType +from typing import Any + +from logHandler import log + +_MISSING = object() +_RUNTIME_LOCK = threading.RLock() +_CONFLICT_PREFIXES = ( + "google", + "pydantic", + "pydantic_core", + "annotated_types", + "typing_extensions", + "websockets", + "httpx", + "httpcore", + "anyio", + "sniffio", +) + + +def _has_prefix(moduleName: str) -> bool: + return any(moduleName == prefix or moduleName.startswith(f"{prefix}.") for prefix in _CONFLICT_PREFIXES) + + +def _collect_conflicting_modules() -> dict[str, ModuleType]: + return {name: module for name, module in sys.modules.items() if _has_prefix(name)} + + +def _load_versions(modules: dict[str, ModuleType], names: tuple[str, ...]) -> dict[str, str]: + versions: dict[str, str] = {} + for name in names: + module = modules.get(name) + if module is None: + continue + version = getattr(module, "__version__", None) + if isinstance(version, str): + versions[name] = version + return versions + + +@dataclass +class VendorRuntime: + libDir: str + genai: Any | None + types: Any | None + pyaudio: ModuleType | None + modules: dict[str, ModuleType] + versions: dict[str, str] + + @property + def genaiAvailable(self) -> bool: + return self.genai is not None and self.types is not None + + @property + def pyaudioAvailable(self) -> bool: + return self.pyaudio is not None + + +def _create_runtime(libDir: str) -> VendorRuntime: + absLibDir = os.path.abspath(libDir) + genai = None + types = None + pyaudio = None + runtimeModules: dict[str, ModuleType] = {} + versions: dict[str, str] = {} + + with _RUNTIME_LOCK: + originalPath = list(sys.path) + originalModules = _collect_conflicting_modules() + try: + sys.path = [absLibDir] + [p for p in sys.path if p != absLibDir] + for moduleName in list(sys.modules.keys()): + if _has_prefix(moduleName): + sys.modules.pop(moduleName, None) + + try: + pyaudio = importlib.import_module("pyaudio") + except Exception: + pyaudio = None + + try: + from google import genai as loadedGenai + from google.genai import types as loadedTypes + + genai = loadedGenai + types = loadedTypes + except Exception: + genai = None + types = None + + runtimeModules = _collect_conflicting_modules() + if pyaudio is not None: + runtimeModules["pyaudio"] = pyaudio + versions = _load_versions( + runtimeModules, + ("google.genai", "pydantic", "websockets", "typing_extensions"), + ) + finally: + sys.path = originalPath + for moduleName in list(sys.modules.keys()): + if _has_prefix(moduleName): + sys.modules.pop(moduleName, None) + sys.modules.update(originalModules) + + if genai is not None and hasattr(genai, "__file__"): + log.info(f"vendor_loader: google.genai loaded from {genai.__file__}") + if pyaudio is not None and hasattr(pyaudio, "__file__"): + log.info(f"vendor_loader: pyaudio loaded from {pyaudio.__file__}") + if versions: + log.info(f"vendor_loader: resolved versions {versions}") + + return VendorRuntime( + libDir=absLibDir, + genai=genai, + types=types, + pyaudio=pyaudio, + modules=runtimeModules, + versions=versions, + ) + + +@contextlib.contextmanager +def runtime_scope(runtime: VendorRuntime): + with _RUNTIME_LOCK: + originalPath = list(sys.path) + moduleSnapshot = {name: sys.modules.get(name, _MISSING) for name in runtime.modules} + prefixBefore = _collect_conflicting_modules() + try: + sys.path = [runtime.libDir] + [p for p in sys.path if p != runtime.libDir] + sys.modules.update(runtime.modules) + yield + for name, module in list(sys.modules.items()): + if _has_prefix(name): + runtime.modules[name] = module + if runtime.pyaudio is not None: + runtime.modules["pyaudio"] = runtime.pyaudio + finally: + for name in list(sys.modules.keys()): + if _has_prefix(name): + sys.modules.pop(name, None) + sys.modules.update(prefixBefore) + for name, originalValue in moduleSnapshot.items(): + if originalValue is _MISSING: + sys.modules.pop(name, None) + else: + sys.modules[name] = originalValue + sys.path = originalPath + + +def load_runtime(libDir: str) -> VendorRuntime: + return _create_runtime(libDir) diff --git a/addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py b/addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py index 15f690d..9dafea7 100644 --- a/addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py +++ b/addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py @@ -22,7 +22,7 @@ FALLBACK_VOICES, ) from ..core.audio_utils import convertToWav, mergeWavFiles, saveBinaryFile, safeStartFile -from ..core.gemini_imports import genai, types, GENAI_AVAILABLE +from ..core.gemini_imports import GENAI_AVAILABLE, genai, getRuntimeScope, types from .. import talkWithAI @@ -253,14 +253,16 @@ def onClose(self, evt: wx.Event) -> None: # Force close the stream if it's active if hasattr(self, "currentStream") and self.currentStream: try: - self.currentStream.close() + with getRuntimeScope(): + self.currentStream.close() except Exception: pass # Close the client if self.client: try: - self.client.close() + with getRuntimeScope(): + self.client.close() except Exception: pass self.Destroy() @@ -421,7 +423,8 @@ def onGenerate(self, evt: wx.Event) -> None: def _generateThread(self, text: str) -> None: ui.message(_("Generating speech, please wait...")) try: - self.client = genai.Client(api_key=self.apiKey) + with getRuntimeScope(): + self.client = genai.Client(api_key=self.apiKey) except Exception as e: log.error(f"Failed init genai client: {e}", exc_info=True) if not self.isClosed: @@ -447,51 +450,52 @@ def handleSuccess(savedPath: str | None) -> None: wx.CallAfter(self.saveBtn.Enable, True) try: - temp = self.tempSlider.GetValue() / 10.0 - styleInstructions = self.styleCtrl.GetValue().strip() - if styleInstructions: - finalText = f"{styleInstructions}\n{text}" - else: - finalText = f"Please read the following text aloud:\n{text}" - - contents = [types.Content(role="user", parts=[types.Part.from_text(text=finalText)])] - - if not self.modeMulti: - voiceName = self._getSelectedVoiceName(self.voiceChoiceSingle, self.selectedVoiceIdx) - speechConfig = types.SpeechConfig( - voice_config=types.VoiceConfig( - prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=voiceName), - ), - ) - else: - speaker1Name = self.spk1NameCtrl.GetValue().strip() or _("Speaker1") - speaker2Name = self.spk2NameCtrl.GetValue().strip() or _("Speaker2") - voice1 = self._getSelectedVoiceName(self.voiceChoiceMulti1, self.selectedVoiceIdx) - voice2 = self._getSelectedVoiceName(self.voiceChoiceMulti2, self.selectedVoiceIdx2) - speechConfig = types.SpeechConfig( - multi_speaker_voice_config=types.MultiSpeakerVoiceConfig( - speaker_voice_configs=[ - types.SpeakerVoiceConfig( - speaker=speaker1Name, - voice_config=types.VoiceConfig( - prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=voice1), + with getRuntimeScope(): + temp = self.tempSlider.GetValue() / 10.0 + styleInstructions = self.styleCtrl.GetValue().strip() + if styleInstructions: + finalText = f"{styleInstructions}\n{text}" + else: + finalText = f"Please read the following text aloud:\n{text}" + + contents = [types.Content(role="user", parts=[types.Part.from_text(text=finalText)])] + + if not self.modeMulti: + voiceName = self._getSelectedVoiceName(self.voiceChoiceSingle, self.selectedVoiceIdx) + speechConfig = types.SpeechConfig( + voice_config=types.VoiceConfig( + prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=voiceName), + ), + ) + else: + speaker1Name = self.spk1NameCtrl.GetValue().strip() or _("Speaker1") + speaker2Name = self.spk2NameCtrl.GetValue().strip() or _("Speaker2") + voice1 = self._getSelectedVoiceName(self.voiceChoiceMulti1, self.selectedVoiceIdx) + voice2 = self._getSelectedVoiceName(self.voiceChoiceMulti2, self.selectedVoiceIdx2) + speechConfig = types.SpeechConfig( + multi_speaker_voice_config=types.MultiSpeakerVoiceConfig( + speaker_voice_configs=[ + types.SpeakerVoiceConfig( + speaker=speaker1Name, + voice_config=types.VoiceConfig( + prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=voice1), + ), ), - ), - types.SpeakerVoiceConfig( - speaker=speaker2Name, - voice_config=types.VoiceConfig( - prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=voice2), + types.SpeakerVoiceConfig( + speaker=speaker2Name, + voice_config=types.VoiceConfig( + prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name=voice2), + ), ), - ), - ], - ), + ], + ), + ) + + generateConfig = types.GenerateContentConfig( + temperature=temp, + response_modalities=["audio"], + speech_config=speechConfig, ) - - generateConfig = types.GenerateContentConfig( - temperature=temp, - response_modalities=["audio"], - speech_config=speechConfig, - ) outPathBase = os.path.join(ADDON_DIR_VAL, "last_audio_generated") if self.isClosed: @@ -546,42 +550,44 @@ def _streamAndSaveAudio( if self.isClosed: return None # Store the stream object - self.currentStream = client.models.generate_content_stream( - model=model, - contents=contents, - config=configObj, - ) + with getRuntimeScope(): + self.currentStream = client.models.generate_content_stream( + model=model, + contents=contents, + config=configObj, + ) - for chunk in self.currentStream: - if self.isClosed: - # Explicitly close the stream iterator to kill connection - try: - self.currentStream.close() - except Exception: - pass - return None - - if not getattr(chunk, "candidates", None): - continue - candidate = chunk.candidates[0] - if not candidate.content or not candidate.content.parts: - continue - part = candidate.content.parts[0] - - if part.inline_data and getattr(part.inline_data, "data", None): - inline = part.inline_data - ext = mimetypes.guess_extension(inline.mime_type or "") or "" - - if not ext or ext.lower() not in (".wav", ".mp3", ".ogg", ".flac"): - wavBytes = convertToWav(inline.data, inline.mime_type) - filename = f"{outPathBase}_{fileIndex}.wav" - saveBinaryFile(filename, wavBytes) - else: - filename = f"{outPathBase}_{fileIndex}{ext}" - saveBinaryFile(filename, inline.data) - - savedPaths.append(filename) - fileIndex += 1 + with getRuntimeScope(): + for chunk in self.currentStream: + if self.isClosed: + # Explicitly close the stream iterator to kill connection + try: + self.currentStream.close() + except Exception: + pass + return None + + if not getattr(chunk, "candidates", None): + continue + candidate = chunk.candidates[0] + if not candidate.content or not candidate.content.parts: + continue + part = candidate.content.parts[0] + + if part.inline_data and getattr(part.inline_data, "data", None): + inline = part.inline_data + ext = mimetypes.guess_extension(inline.mime_type or "") or "" + + if not ext or ext.lower() not in (".wav", ".mp3", ".ogg", ".flac"): + wavBytes = convertToWav(inline.data, inline.mime_type) + filename = f"{outPathBase}_{fileIndex}.wav" + saveBinaryFile(filename, wavBytes) + else: + filename = f"{outPathBase}_{fileIndex}{ext}" + saveBinaryFile(filename, inline.data) + + savedPaths.append(filename) + fileIndex += 1 if not savedPaths: wx.CallAfter( diff --git a/addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py b/addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py index a6b5ea5..0d435a5 100644 --- a/addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py +++ b/addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- import wx -import sys import threading import asyncio import traceback +import random +import time from logHandler import log import addonHandler @@ -13,25 +14,15 @@ import struct -addonHandler.initTranslation() - -# Ensure lib directory is in path -addonDir = os.path.dirname(os.path.abspath(__file__)) -libDir = os.path.join(addonDir, "lib") -if libDir not in sys.path: - sys.path.insert(0, libDir) +from .core.gemini_imports import ( + GENAI_AVAILABLE, + PYAUDIO_AVAILABLE, + genai, + getRuntimeScope, + pyaudio, +) -try: - import pyaudio -except ImportError: - pyaudio = None - log.warning("talkWithAI: PyAudio not found.") - -try: - from google import genai -except ImportError: - genai = None - log.warning("talkWithAI: Google GenAI not found.") +addonHandler.initTranslation() MODEL_NAME = "gemini-2.5-flash-native-audio-preview-12-2025" @@ -45,6 +36,13 @@ OUTPUT_RATE = 24000 CHUNK = 1024 BUFFER_THRESHOLD = 5 +MIN_BUFFER_THRESHOLD = 2 +MAX_BUFFER_THRESHOLD = 10 +BACKOFF_BASE_SECONDS = 1.0 +BACKOFF_MAX_SECONDS = 20.0 +BACKOFF_JITTER_SECONDS = 0.4 +MEMORY_MAX_LINES = 12 +MEMORY_MAX_CHARS = 1800 class TalkWithAIDialog(wx.Dialog): @@ -68,6 +66,12 @@ def __init__(self, parent, apiKey, voiceName, systemInstruction): self.isPlaying = False self.playThread = None self.volume = 80 # Default volume percentage + self.bufferThreshold = BUFFER_THRESHOLD + self.lastBufferAdjustAt = 0.0 + self.lastStatusAt = 0.0 + self.memoryEnabled = True + self.sessionMemory = [] + self.memoryLock = threading.Lock() # Audio Device Selection self.inputDevices = self._getDeviceList(input=True) @@ -77,13 +81,13 @@ def __init__(self, parent, apiKey, voiceName, systemInstruction): self._buildUi() - if not pyaudio: + if not PYAUDIO_AVAILABLE: wx.CallAfter( self.reportError, _("PyAudio library is not installed. This feature requires PyAudio."), ) self.connectBtn.Disable() - if not genai: + if not GENAI_AVAILABLE: wx.CallAfter(self.reportError, _("Google GenAI library is not installed.")) self.connectBtn.Disable() @@ -93,9 +97,10 @@ def __init__(self, parent, apiKey, voiceName, systemInstruction): def _getDeviceList(self, input=True): """Returns a list of dicts: {'index': int, 'name': str}""" devices = [] - if not pyaudio: + if not PYAUDIO_AVAILABLE: return devices - p = pyaudio.PyAudio() + with getRuntimeScope(): + p = pyaudio.PyAudio() try: info = p.get_host_api_info_by_index(0) numDevices = info.get("deviceCount") @@ -186,6 +191,17 @@ def _buildUi(self): self.googleSearchCb.SetValue(False) controlsSizer.Add(self.googleSearchCb, 0, wx.ALL | wx.EXPAND, 5) + # Translators: Checkbox to enable temporary conversation memory during this dialog session. + self.memoryCb = wx.CheckBox(panel, label=_("Use session memory")) + self.memoryCb.SetValue(True) + self.memoryCb.Bind(wx.EVT_CHECKBOX, self.onMemoryToggle) + controlsSizer.Add(self.memoryCb, 0, wx.ALL | wx.EXPAND, 5) + + # Translators: Button to clear temporary conversation memory for the current dialog session. + self.clearMemoryBtn = wx.Button(panel, label=_("Clear memory now")) + self.clearMemoryBtn.Bind(wx.EVT_BUTTON, self.onClearMemory) + controlsSizer.Add(self.clearMemoryBtn, 0, wx.ALL | wx.EXPAND, 5) + # Volume Slider volSizer = wx.BoxSizer(wx.HORIZONTAL) volLabel = wx.StaticText(panel, label=_("Volume:")) @@ -225,13 +241,75 @@ def onMicToggle(self, evt): def onVolumeChange(self, evt): self.volume = self.volSlider.GetValue() + def onMemoryToggle(self, evt): + self.memoryEnabled = self.memoryCb.GetValue() + if not self.memoryEnabled: + self._clearSessionMemory() + if self.sessionActive: + self.clearMemoryBtn.Hide() + else: + self.clearMemoryBtn.Show(self.memoryEnabled) + self.Layout() + + def onClearMemory(self, evt): + self._clearSessionMemory() + self.updateStatus(_("Memory cleared")) + + def _clearSessionMemory(self): + with self.memoryLock: + self.sessionMemory = [] + + def _rememberMemoryLine(self, line): + if not line: + return + cleaned = str(line).strip() + if not cleaned: + return + with self.memoryLock: + self.sessionMemory.append(cleaned) + if len(self.sessionMemory) > MEMORY_MAX_LINES: + self.sessionMemory = self.sessionMemory[-MEMORY_MAX_LINES:] + totalChars = sum(len(item) for item in self.sessionMemory) + while self.sessionMemory and totalChars > MEMORY_MAX_CHARS: + totalChars -= len(self.sessionMemory.pop(0)) + + def _memorySummary(self): + with self.memoryLock: + if not self.sessionMemory: + return "" + return "\n".join(f"- {line}" for line in self.sessionMemory[-MEMORY_MAX_LINES:]) + + def _buildSystemInstruction(self): + baseRules = ( + "You are a voice assistant for blind and low-vision users. " + "Never fabricate facts. If uncertain, explicitly say you are not sure." + ) + userInstruction = self.systemInstruction.strip() if self.systemInstruction else "" + parts = [baseRules] + if userInstruction: + parts.append(f"User preference:\n{userInstruction}") + if self.memoryEnabled: + summary = self._memorySummary() + if summary: + parts.append(f"Session memory:\n{summary}") + return "\n\n".join(parts) + + def _buildReconnectDelay(self, attempt): + baseDelay = min(BACKOFF_MAX_SECONDS, BACKOFF_BASE_SECONDS * (2 ** max(0, attempt - 1))) + return baseDelay + random.uniform(0.0, BACKOFF_JITTER_SECONDS) + def onConnect(self, evt): self.connectBtn.Disable() self.disconnectBtn.Enable() # Store state and hide checkbox self.useGoogleSearch = self.googleSearchCb.GetValue() + self.memoryEnabled = self.memoryCb.GetValue() + if not self.memoryEnabled: + self._clearSessionMemory() self.googleSearchCb.Hide() + self.memoryCb.Disable() + self.clearMemoryBtn.Hide() # Get selected devices inSel = self.inputChoice.GetSelection() @@ -290,6 +368,7 @@ def onCharHook(self, evt): def onClose(self, evt: wx.Event): self.sessionActive = False self.isPlaying = False + self._clearSessionMemory() # Drain and clear audio queue while not self.audioQueue.empty(): @@ -383,6 +462,7 @@ def _audioPlayerWorker(self): """ buffer = [] buffering = True + self.bufferThreshold = BUFFER_THRESHOLD while self.sessionActive and self.isPlaying: try: @@ -413,7 +493,7 @@ def _audioPlayerWorker(self): if buffering: buffer.append(data) - if len(buffer) >= BUFFER_THRESHOLD: + if len(buffer) >= self.bufferThreshold: buffering = False # Play accumulated buffer if self.outputStream and self.outputStream.is_active(): @@ -424,12 +504,26 @@ def _audioPlayerWorker(self): # Direct play if self.outputStream and self.outputStream.is_active(): self.outputStream.write(data) + queueDepth = self.audioQueue.qsize() + now = time.monotonic() + if queueDepth > self.bufferThreshold + 3 and self.bufferThreshold > MIN_BUFFER_THRESHOLD: + if now - self.lastBufferAdjustAt > 1.0: + self.bufferThreshold -= 1 + self.lastBufferAdjustAt = now + elif queueDepth <= 1 and self.bufferThreshold < MAX_BUFFER_THRESHOLD: + if now - self.lastBufferAdjustAt > 1.0: + self.bufferThreshold += 1 + self.lastBufferAdjustAt = now except queue.Empty: # If queue is empty, we have run out of audio data. # To prevent micro-stuttering, we switch back to buffering mode. if not buffering and self.sessionActive: buffering = True + now = time.monotonic() + if self.bufferThreshold < MAX_BUFFER_THRESHOLD and now - self.lastBufferAdjustAt > 0.8: + self.bufferThreshold += 1 + self.lastBufferAdjustAt = now continue except Exception as e: log.error(f"Audio Player Error: {e}") @@ -479,6 +573,14 @@ async def receiveLoop(self, session): log.debug("TalkWithAI: Turn Complete") continue + inputTranscription = getattr(response.server_content, "input_transcription", None) + if inputTranscription and getattr(inputTranscription, "text", None): + self._rememberMemoryLine(f"User: {inputTranscription.text}") + + outputTranscription = getattr(response.server_content, "output_transcription", None) + if outputTranscription and getattr(outputTranscription, "text", None): + self._rememberMemoryLine(f"Assistant: {outputTranscription.text}") + modelTurn = response.server_content.model_turn if modelTurn is not None: for part in modelTurn.parts: @@ -486,6 +588,9 @@ async def receiveLoop(self, session): audioData = part.inline_data.data # Push to queue instead of writing directly self.audioQueue.put(audioData) + textPart = getattr(part, "text", None) + if textPart: + self._rememberMemoryLine(f"Assistant: {textPart}") except Exception as e: log.error(f"TalkWithAI Receive Loop Error: {e}") finally: @@ -496,7 +601,8 @@ async def receiveLoop(self, session): async def runSession(self): try: # Setup Audio (Once for the entire session duration) - self.audioInterface = pyaudio.PyAudio() + with getRuntimeScope(): + self.audioInterface = pyaudio.PyAudio() # Output Stream (Speaker) self.outputStream = self.audioInterface.open( @@ -519,74 +625,80 @@ async def runSession(self): ) # Initialize Client - self.client = genai.Client(api_key=self.apiKey, http_options={"api_version": "v1alpha"}) - - # config object contains generation_config - toolsConfig = [] - if self.useGoogleSearch: - toolsConfig.append({"google_search": {}}) - - config = { - "response_modalities": ["AUDIO"], - "tools": toolsConfig, - "generation_config": { - "speech_config": { - "voice_config": {"prebuilt_voice_config": {"voice_name": self.voiceName}}, - }, - }, - "system_instruction": {"parts": [{"text": self.systemInstruction}]} - if self.systemInstruction - else None, - } + with getRuntimeScope(): + self.client = genai.Client(api_key=self.apiKey, http_options={"api_version": "v1alpha"}) firstConnect = True + retryAttempt = 0 # Main Reconnection Loop while self.sessionActive: try: + toolsConfig = [] + if self.useGoogleSearch: + toolsConfig.append({"google_search": {}}) + systemInstruction = self._buildSystemInstruction() + config = { + "response_modalities": ["AUDIO"], + "tools": toolsConfig, + "generation_config": { + "speech_config": { + "voice_config": {"prebuilt_voice_config": {"voice_name": self.voiceName}}, + }, + }, + "system_instruction": {"parts": [{"text": systemInstruction}]}, + } log.debug("TalkWithAI: Connecting to Gemini Live...") - async with self.client.aio.live.connect(model=MODEL_NAME, config=config) as session: - if firstConnect: - wx.CallAfter(self.updateStatus, _("Connected")) - # Play start sound only on the very first successful connection - self._playSoundEffect(STREAM_START_SOUND_PATH) - firstConnect = False - else: - log.debug("TalkWithAI: Reconnected silently") - - self.session = session - - # Start sending and receiving tasks - sendTask = asyncio.create_task(self.sendAudioLoop(session)) - receiveTask = asyncio.create_task(self.receiveLoop(session)) - - if not self.isPlaying: - playWorker = threading.Thread(target=self._audioPlayerWorker, daemon=True) - self.isPlaying = True - playWorker.start() - - # Wait for either task to finish - # If connection drops, receiveLoop finishes. - # We then cancel sendTask and reconnect. - _done, pending = await asyncio.wait( - [sendTask, receiveTask], - return_when=asyncio.FIRST_COMPLETED, - ) - - # Cancel pending tasks (e.g. send loop if receive died) - for task in pending: - task.cancel() - try: - await task - except asyncio.CancelledError: - pass + with getRuntimeScope(): + async with self.client.aio.live.connect(model=MODEL_NAME, config=config) as session: + retryAttempt = 0 + if firstConnect: + wx.CallAfter(self.updateStatus, _("Connected")) + # Play start sound only on the very first successful connection + self._playSoundEffect(STREAM_START_SOUND_PATH) + firstConnect = False + else: + log.debug("TalkWithAI: Reconnected silently") + + self.session = session + + # Start sending and receiving tasks + sendTask = asyncio.create_task(self.sendAudioLoop(session)) + receiveTask = asyncio.create_task(self.receiveLoop(session)) + + if not self.isPlaying: + playWorker = threading.Thread(target=self._audioPlayerWorker, daemon=True) + self.isPlaying = True + playWorker.start() + + # Wait for either task to finish + # If connection drops, receiveLoop finishes. + # We then cancel sendTask and reconnect. + _done, pending = await asyncio.wait( + [sendTask, receiveTask], + return_when=asyncio.FIRST_COMPLETED, + ) + + # Cancel pending tasks (e.g. send loop if receive died) + for task in pending: + task.cancel() + try: + await task + except asyncio.CancelledError: + pass except Exception as e: log.error(f"TalkWithAI Session/Connection Error: {e}") - # Only play end sound if we are giving up (session not active) - # or just notify user of retry - wx.CallAfter(self.updateStatus, _("Connection Lost. Retrying...")) - await asyncio.sleep(2) # Backoff before reconnect + retryAttempt += 1 + delay = self._buildReconnectDelay(retryAttempt) + now = time.monotonic() + if now - self.lastStatusAt > 1.0: + wx.CallAfter( + self.updateStatus, + _("Connection lost. Retrying in {seconds:.1f}s").format(seconds=delay), + ) + self.lastStatusAt = now + await asyncio.sleep(delay) if self.sessionActive: log.debug("TalkWithAI: Reconnecting...") @@ -621,6 +733,8 @@ def resetUi(self): self.connectBtn.Enable() self.disconnectBtn.Disable() self.googleSearchCb.Show() + self.memoryCb.Enable() + self.clearMemoryBtn.Show(self.memoryCb.GetValue()) # Show device selection again for child in self.deviceSizer.GetChildren(): diff --git a/addon/locale/es/LC_MESSAGES/nvda.po b/addon/locale/es/LC_MESSAGES/nvda.po index 5f2b6e1..a8726ff 100644 --- a/addon/locale/es/LC_MESSAGES/nvda.po +++ b/addon/locale/es/LC_MESSAGES/nvda.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: Native_Speech_generation 1.0\n" +"Project-Id-Version: 'NativeSpeechGeneration' '1.5.6'\n" "Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n" -"POT-Creation-Date: 2026-02-07 13:00+0700\n" -"PO-Revision-Date: 2026-02-10 07:27+0700\n" +"POT-Creation-Date: 2026-02-20 16:58+0700\n" +"PO-Revision-Date: 2026-02-20 17:12+0700\n" "Last-Translator: \n" "Language-Team: \n" "Language: es\n" @@ -44,20 +44,20 @@ msgstr "" #: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:97 #: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:153 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:217 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:218 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:153 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:344 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:361 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:381 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:392 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:400 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:409 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:431 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:521 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:590 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:613 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:652 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:233 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:234 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:146 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:346 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:363 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:383 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:394 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:402 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:411 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:434 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:525 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:596 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:619 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:658 #: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:126 msgid "Error" msgstr "Error" @@ -100,8 +100,8 @@ msgid "" "Are you sure you want to reinstall the libraries? This will redownload the " "dependencies and require an NVDA restart." msgstr "" -"¿Estás segura de que quieres reinstalar las librerías? Esto volverá a " -"descargar las dependencias y requerirá un reinicio de NVDA." +"Seguro que quieres reinstalar las librerías? Esto volverá a descargar las " +"dependencias y requerirá un reinicio de NVDA." #: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:166 #: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:88 @@ -121,120 +121,134 @@ msgid "Missing Dependencies" msgstr "Dependencias faltantes" #. Translators: Title of the dialog for the "Talk With AI" feature (REAL-TIME conversation). -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:53 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:51 msgid "Talk With AI" msgstr "Hablar con IA" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:83 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:87 msgid "PyAudio library is not installed. This feature requires PyAudio." msgstr "" "La librería PyAudio no está instalada. Esta característica requiere PyAudio." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:87 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:91 msgid "Google GenAI library is not installed." msgstr "La librería Google GenAI no está instalada." #. 1. Status Area #. Translators: Label for the status area showing connection state. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:124 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:129 msgid "Status" msgstr "Estado" #. Translators: Initial status message when the dialog opens. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:127 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:132 msgid "Ready to Connect" msgstr "Listo para conectar" #. 2. Controls Area -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:132 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:137 msgid "Controls" msgstr "Controles" #. Translators: Button to start the voice conversation. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:138 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:143 msgid "Start Conversation" msgstr "Iniciar conversación" #. Translators: Button to stop the voice conversation. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:141 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:146 msgid "Stop Conversation" msgstr "Detener conversación" #. Mic Toggle #. Translators: Toggle button label indicating microphone is ON. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:151 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:222 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:156 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:238 msgid "Microphone: ON" msgstr "Micrófono: ENCENDIDO" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:161 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:166 msgid "Microphone:" msgstr "Micrófono:" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:172 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:177 msgid "Speaker:" msgstr "Altavoz:" #. Google Search Checkbox #. Translators: Checkbox to enable "Grounding", allowing the AI to search Google for answers. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:185 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:190 msgid "Grounding with Google Search" msgstr "Contextualización con Búsqueda de Google" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:191 +#. Translators: Checkbox to enable temporary conversation memory during this dialog session. +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:195 +msgid "Use session memory" +msgstr "" + +#. Translators: Button to clear temporary conversation memory for the current dialog session. +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:201 +msgid "Clear memory now" +msgstr "" + +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:207 msgid "Volume:" msgstr "Volumen:" #. 3. Info Area (Voice only) #. Translators: Label for the selected voice -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:203 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:219 msgid "Voice: " msgstr "Voz: " -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:213 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:229 msgid "Status: " msgstr "Estado: " -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:222 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:238 msgid "Microphone: OFF" msgstr "Micrófono: APAGADO" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:259 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:256 +msgid "Memory cleared" +msgstr "" + +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:337 msgid "Connecting..." msgstr "Conectando..." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:267 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:345 msgid "Disconnecting..." msgstr "Desconectando..." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:550 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:656 msgid "Connected" msgstr "Conectado" -#. Only play end sound if we are giving up (session not active) -#. or just notify user of retry -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:588 -msgid "Connection Lost. Retrying..." +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:698 +#, fuzzy, python-brace-format +#| msgid "Connection Lost. Retrying..." +msgid "Connection lost. Retrying in {seconds:.1f}s" msgstr "Conexión perdida. Reintentando..." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:638 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:752 msgid "Ready" msgstr "Listo" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:69 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:122 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:61 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:115 msgid "Open the Native Speech Generation dialog" msgstr "Abrir el diálogo de Native Speech Generation" #. Translators: Title of the settings panel in NVDA preferences. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:70 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:123 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:62 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:116 #: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:29 #: buildVars.py:6 msgid "Native Speech Generation" msgstr "Native Speech Generation" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:77 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:69 msgid "" "Native Speech Generation is installing dependencies. Please restart NVDA for " "the changes to take effect." @@ -243,35 +257,35 @@ msgstr "" "NVDA para que los cambios surtan efecto." #. Translators: Title of the information dialog recommending a restart. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:80 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:73 #: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:115 msgid "Restart Required" msgstr "Requiere reinicio" #. Translators: Name of the add-on in the NVDA Tools menu. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:115 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:108 msgid "&Native Speech Generation" -msgstr "Generación de voz &Nativa" +msgstr "&Native Speech Generation" #. Translators: Tooltip or description for the menu item. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:117 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:110 msgid "Generate speech using Gemini TTS" msgstr "Generar voz usando Gemini TTS" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:137 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:130 msgid "" "The Native Speech Generation add-on is already open. Please close the dialog " "before opening it again." msgstr "" -"El complemento Native Speech Generation ya está abierto. Por favor, cierra " +"El complemento Native Speech Generation ya está abierto. Por favor, cierra " "el diálogo antes de volver a abrirlo." #. Translators: Title of warning dialog when user tries to open the add-on twice. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:140 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:133 msgid "Add-on Already Running" msgstr "Complemento ya en ejecución" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:152 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:145 #, python-brace-format msgid "Failed to open Native Speech Generation dialog: {error}" msgstr "Fallo al abrir el diálogo de Native Speech Generation: {error}" @@ -285,7 +299,7 @@ msgstr "Native Speech Generation (Gemini TTS)" #. Translators: Label for the text area where user inputs text to be converted to speech. #: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:73 msgid "&Type text to convert here:" -msgstr "Escriba el texto para convertir &aquí:" +msgstr "&Escribir el texto para convertir aquí:" #. Style Input #. Translators: Label for optional instructions on how the speech should be spoken (e.g. "Happy", "Sad"). @@ -329,7 +343,7 @@ msgstr "Temperatura:" #. Translators: Button to start generating the speech audio. #: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:147 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:529 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:533 msgid "&Generate Speech" msgstr "&Generar voz" @@ -379,7 +393,7 @@ msgid "Speaker 1 Name:" msgstr "Nombre del hablante 1:" #: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:219 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:467 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:471 msgid "Speaker1" msgstr "Hablante1" @@ -393,15 +407,15 @@ msgid "Speaker 2 Name:" msgstr "Nombre del hablante 2:" #: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:235 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:468 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:472 msgid "Speaker2" msgstr "Hablante2" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:343 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:345 msgid "Talk With AI module is missing." msgstr "El módulo Hablar con IA no está instalado." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:353 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:355 msgid "" "Talk With AI currently does not support multi-speaker mode. Please select " "Single-speaker." @@ -409,103 +423,103 @@ msgstr "" "Hablar con IA actualmente no soporta el modo de múltiples hablantes. Por " "favor, selecciona Un solo hablante." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:355 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:357 msgid "Feature Limitation" msgstr "Limitación de característica" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:361 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:363 msgid "No GEMINI_API_KEY configured." msgstr "No se ha configurado la clave de API de Gemini." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:380 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:382 #, python-brace-format msgid "Failed to open Talk With AI: {error}" msgstr "Fallo al abrir Hablar con IA: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:391 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:393 msgid "google-genai library not installed. Please restart NVDA." msgstr "la librería google-genai no está instalada. Por favor, reinicia NVDA." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:399 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:401 msgid "No GEMINI_API_KEY configured. Set it in NVDA settings." msgstr "" -"No se ha configurado la clave de API de Gemini. Conjúrala en la " -"configuración de NVDA." +"No se ha configurado la clave de API de Gemini. Establécela en los ajustes " +"de NVDA." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:408 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:410 msgid "Please enter text to generate." msgstr "Por favor, introduce texto para generar." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:415 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:417 msgid "Generating..." msgstr "Generando..." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:422 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:424 msgid "Generating speech, please wait..." msgstr "Generando voz, por favor espera..." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:430 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:433 #, python-brace-format msgid "Failed to initialize Google GenAI client: {error}" msgstr "Fallo al inicializar el cliente de Google GenAI: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:441 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:444 msgid "Failed to generate audio." msgstr "Fallo al generar audio." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:443 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:446 msgid "Generation complete." msgstr "Generación completa." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:516 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:520 msgid "An error occurred during generation." msgstr "Ocurrió un error durante la generación." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:520 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:524 #, python-brace-format msgid "An unexpected error occurred: {error}" msgstr "Ocurrió un error inesperado: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:589 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:595 msgid "No inline audio data returned by model." msgstr "El modelo no devolvió datos de audio en línea." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:612 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:618 #, python-brace-format msgid "Failed to generate speech: {error}" msgstr "Fallo al generar voz: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:631 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:637 msgid "Save Audio File" msgstr "Guardar archivo de audio" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:632 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:638 msgid "WAV files (*.wav)|*.wav|MP3 files (*.mp3)|*.mp3" msgstr "Archivos WAV (*.wav)|*.wav|Archivos MP3 (*.mp3)|*.mp3" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:644 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:650 #, python-brace-format msgid "Audio saved to {path}" msgstr "Audio guardado en {path}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:645 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:651 msgid "Success" msgstr "Éxito" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:651 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:657 #, python-brace-format msgid "Failed to save audio: {error}" msgstr "Fallo al guardar audio: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:666 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:672 msgid "Sample not available" msgstr "Muestra no disponible" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:671 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:677 msgid "Playing voice sample" msgstr "Reproduciendo muestra de voz" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:676 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:682 msgid "Failed to play sample" msgstr "Fallo al reproducir muestra" @@ -539,7 +553,7 @@ msgid "" msgstr "" "Esto eliminará la librería existente y reiniciará NVDA para volver a " "descargarla.\n" -"¿Estás segura?" +"¿Estás seguro?" #: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:114 msgid "" @@ -601,14 +615,21 @@ msgstr "" #: buildVars.py:18 msgid "" -"- Stability: Restored previous dependency handling to resolve crashes (pyo3 " -"panic).\n" -"- Localization: Fixed translation issues for Interface and Settings " -"dialogs.\n" -"- Fix: Resolved SSL Certificate path error.\n" +"- Talk With AI: Added optional session memory and a clear-memory control.\n" +"- Talk With AI: Improved stream stability with reconnect backoff/retry and " +"adaptive buffering.\n" +"- Documentation: Added Spanish-language documentation.\n" msgstr "" -"- Estabilidad: Restaurado el manejo previo de dependencias para resolver " -"bloqueos (pyo3 panic).\n" -"- Localización: Solucionados problemas de traducción en los diálogos de " -"Interfaz y Configuración.\n" -"- Corrección: Resuelto el error de la ruta del certificado SSL.\n" + +#~ msgid "" +#~ "- Stability: Restored previous dependency handling to resolve crashes " +#~ "(pyo3 panic).\n" +#~ "- Localization: Fixed translation issues for Interface and Settings " +#~ "dialogs.\n" +#~ "- Fix: Resolved SSL Certificate path error.\n" +#~ msgstr "" +#~ "- Estabilidad: Restaurado el manejo previo de dependencias para resolver " +#~ "bloqueos (pyo3 panic).\n" +#~ "- Localización: Solucionados problemas de traducción en los diálogos de " +#~ "Interfaz y Configuración.\n" +#~ "- Corrección: Resuelto el error de la ruta del certificado SSL.\n" diff --git a/addon/locale/id/LC_MESSAGES/nvda.po b/addon/locale/id/LC_MESSAGES/nvda.po index 3fa9246..c8cdafe 100644 --- a/addon/locale/id/LC_MESSAGES/nvda.po +++ b/addon/locale/id/LC_MESSAGES/nvda.po @@ -6,10 +6,10 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: 'NativeSpeechGeneration' '1.0'\n" +"Project-Id-Version: 'NativeSpeechGeneration' '1.5.6'\n" "Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n" -"POT-Creation-Date: 2026-01-29 13:12+0700\n" -"PO-Revision-Date: 2026-01-29 13:18+0700\n" +"POT-Creation-Date: 2026-02-20 16:58+0700\n" +"PO-Revision-Date: 2026-02-20 17:15+0700\n" "Last-Translator: \n" "Language-Team: \n" "Language: id\n" @@ -49,21 +49,21 @@ msgstr "" #: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:97 #: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:153 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:217 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:218 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:153 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:343 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:360 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:380 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:391 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:399 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:408 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:430 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:517 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:586 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:609 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:648 -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:124 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:233 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:234 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:146 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:346 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:363 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:383 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:394 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:402 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:411 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:434 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:525 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:596 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:619 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:658 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:126 msgid "Error" msgstr "Kesalahan" @@ -107,7 +107,7 @@ msgstr "" "dependensi dan memerlukan restart NVDA." #: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:166 -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:86 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:88 msgid "Confirm Reinstall" msgstr "Konfirmasikan Instal Ulang" @@ -124,119 +124,132 @@ msgid "Missing Dependencies" msgstr "Kehilangan dependensi" #. Translators: Title of the dialog for the "Talk With AI" feature (REAL-TIME conversation). -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:53 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:51 msgid "Talk With AI" msgstr "Bicara Dengan AI" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:83 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:87 msgid "PyAudio library is not installed. This feature requires PyAudio." msgstr "Perpustakaan PyAudio tidak diinstal. Fitur ini memerlukan PyAudio." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:87 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:91 msgid "Google GenAI library is not installed." msgstr "Pustaka Google GenAI tidak terpasang." #. 1. Status Area #. Translators: Label for the status area showing connection state. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:124 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:129 msgid "Status" msgstr "Status" #. Translators: Initial status message when the dialog opens. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:127 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:132 msgid "Ready to Connect" msgstr "Siap Terhubung" #. 2. Controls Area -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:132 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:137 msgid "Controls" msgstr "Controls" #. Translators: Button to start the voice conversation. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:138 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:143 msgid "Start Conversation" msgstr "Mulai Percakapan" #. Translators: Button to stop the voice conversation. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:141 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:146 msgid "Stop Conversation" msgstr "Akhiri Percakapan" #. Mic Toggle #. Translators: Toggle button label indicating microphone is ON. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:151 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:222 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:156 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:238 msgid "Microphone: ON" msgstr "Mikrofon: AKTIF" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:161 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:166 msgid "Microphone:" msgstr "Mikrofon:" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:172 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:177 msgid "Speaker:" msgstr "Speaker:" #. Google Search Checkbox #. Translators: Checkbox to enable "Grounding", allowing the AI to search Google for answers. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:185 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:190 msgid "Grounding with Google Search" msgstr "Grounding dengan Google Search" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:191 +#. Translators: Checkbox to enable temporary conversation memory during this dialog session. +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:195 +msgid "Use session memory" +msgstr "Gunakan memori untuk sesi ini" + +#. Translators: Button to clear temporary conversation memory for the current dialog session. +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:201 +msgid "Clear memory now" +msgstr "Hapus memori sekarang" + +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:207 msgid "Volume:" msgstr "Volume:" #. 3. Info Area (Voice only) #. Translators: Label for the selected voice -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:203 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:219 msgid "Voice: " msgstr "Suara: " -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:213 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:229 msgid "Status: " msgstr "Status: " -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:222 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:238 msgid "Microphone: OFF" msgstr "Mikrofon: NONAKTIF" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:259 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:256 +msgid "Memory cleared" +msgstr "Memori telah dibersihkan" + +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:337 msgid "Connecting..." msgstr "Menghubungkan..." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:267 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:345 msgid "Disconnecting..." msgstr "Memutuskan koneksi..." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:550 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:656 msgid "Connected" msgstr "Terhubung" -#. Only play end sound if we are giving up (session not active) -#. or just notify user of retry -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:588 -msgid "Connection Lost. Retrying..." -msgstr "Koneksi Hilang. Mencoba lagi..." +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:698 +#, python-brace-format +msgid "Connection lost. Retrying in {seconds:.1f}s" +msgstr "Koneksi terputus. Mencoba lagi dalam {seconds:.1f}s" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:638 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:752 msgid "Ready" msgstr "Siap" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:69 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:122 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:61 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:115 msgid "Open the Native Speech Generation dialog" msgstr "Membuka add-on Native Speech Generation" #. Translators: Title of the settings panel in NVDA preferences. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:70 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:123 -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:27 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:62 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:116 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:29 #: buildVars.py:6 msgid "Native Speech Generation" msgstr "Native Speech Generation" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:77 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:69 msgid "" "Native Speech Generation is installing dependencies. Please restart NVDA for " "the changes to take effect." @@ -245,22 +258,22 @@ msgstr "" "perubahan berlaku." #. Translators: Title of the information dialog recommending a restart. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:80 -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:113 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:73 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:115 msgid "Restart Required" msgstr "Restart diperlukan" #. Translators: Name of the add-on in the NVDA Tools menu. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:115 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:108 msgid "&Native Speech Generation" msgstr "&Native Speech Generation" #. Translators: Tooltip or description for the menu item. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:117 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:110 msgid "Generate speech using Gemini TTS" msgstr "Hasilkan Ucapan Menggunakan Gemini TTS" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:137 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:130 msgid "" "The Native Speech Generation add-on is already open. Please close the dialog " "before opening it again." @@ -269,141 +282,141 @@ msgstr "" "membukanya lagi." #. Translators: Title of warning dialog when user tries to open the add-on twice. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:140 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:133 msgid "Add-on Already Running" msgstr "Add-on sudah berjalan" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:152 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:145 #, python-brace-format msgid "Failed to open Native Speech Generation dialog: {error}" msgstr "Gagal menjalankan add-on Native Speech Generation: {error}" #. Translators: The title of the main dialog window for generating speech. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:47 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:48 msgid "Native Speech Generation (Gemini TTS)" msgstr "Native Speech Generation (Gemini TTS)" #. Text Input #. Translators: Label for the text area where user inputs text to be converted to speech. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:72 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:73 msgid "&Type text to convert here:" msgstr "&Masukkan teks yang ingin anda jadikan audio:" #. Style Input #. Translators: Label for optional instructions on how the speech should be spoken (e.g. "Happy", "Sad"). -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:79 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:80 msgid "&Style instructions (optional):" msgstr "&Gaya bicara TTS (optional):" #. Translators: Label for selecting the AI model to use for generation. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:87 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:88 msgid "Select &Model:" msgstr "Pilih &Model:" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:88 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:89 msgid "Flash (Standard Quality)" msgstr "Flash (kualitas standar)" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:88 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:89 msgid "Pro (High Quality)" msgstr "Pro (kualitas tinggi)" #. Translators: Radio button to select single speaker mode. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:95 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:96 msgid "Single-speaker" msgstr "Satu pembicara" #. Translators: Radio button to select multi-speaker mode. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:97 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:98 msgid "Multi-speaker (2)" msgstr "Multi pembicara" #. Settings Toggle #. Translators: Checkbox to show advanced settings like Temperature. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:107 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:108 msgid "Advanced Settings (&Temperature)" msgstr "Pengaturan lanjutan (&Temperature)" #. Translators: Label for the temperature slider which controls creativity of the AI. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:118 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:119 msgid "Temperature:" msgstr "Temperature:" #. Translators: Button to start generating the speech audio. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:146 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:525 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:147 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:533 msgid "&Generate Speech" msgstr "&Hasilkan Audio" #. Translators: Button to play the generated audio. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:151 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:152 msgid "&Play" msgstr "&Putar" #. Translators: Button to save the generated audio to a file. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:157 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:158 msgid "Save &Audio" msgstr "Simpan &Audio" #. Talk With AI Button #. Translators: Button to open the real-time conversation dialog. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:166 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:167 msgid "Talk With &AI" msgstr "Bicara Dengan & AI" #. Translators: Button to open settings specifically for configuring the API key. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:173 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:174 msgid "API Key Settings" msgstr "Pengaturan Kunci API" #. Translators: Button that opens a web browser to view available voices in Google AI Studio. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:176 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:177 msgid "View voices in AI Studio" msgstr "Periksa Suara di AI Studio" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:182 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:183 msgid "&Close" msgstr "&Tutup" #. Translators: Label for selecting a voice in single speaker mode. -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:200 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:201 msgid "Select &Voice:" msgstr "Pilih &Suara:" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:201 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:220 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:236 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:202 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:221 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:237 msgid "Loading voices..." msgstr "Memuat suara ..." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:217 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:218 msgid "Speaker 1 Name:" msgstr "Nama Pembicara 1:" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:218 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:463 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:219 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:471 msgid "Speaker1" msgstr "Pembicara1" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:219 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:235 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:220 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:236 msgid "Voice:" msgstr "Suara:" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:233 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:234 msgid "Speaker 2 Name:" msgstr "Nama Pembicara 2:" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:234 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:464 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:235 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:472 msgid "Speaker2" msgstr "Pembicara2" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:342 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:345 msgid "Talk With AI module is missing." msgstr "Modul Bicara Dengan AI tidak ada." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:352 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:355 msgid "" "Talk With AI currently does not support multi-speaker mode. Please select " "Single-speaker." @@ -411,131 +424,131 @@ msgstr "" "Talk With AI saat ini tidak mendukung mode multi-speaker. Harap pilih " "singgle speaker." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:354 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:357 msgid "Feature Limitation" msgstr "Batasan Fitur" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:360 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:363 msgid "No GEMINI_API_KEY configured." msgstr "" "Tidak ada GEMINI_API_KEY yang dimasukkan, silahkan atur terlebih dahulu." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:379 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:382 #, python-brace-format msgid "Failed to open Talk With AI: {error}" msgstr "Gagal membuka Bicara Dengan AI: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:390 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:393 msgid "google-genai library not installed. Please restart NVDA." msgstr "perpustakaan Google-Genai tidak diinstal. Harap restart NVDA." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:398 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:401 msgid "No GEMINI_API_KEY configured. Set it in NVDA settings." msgstr "" "Tidak ada kunci API Gemini yang anda masukkan. Silahkan atur terlebih " "dahulu di pengaturan NVDA, kategory NativeSpeechGeneration." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:407 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:410 msgid "Please enter text to generate." msgstr "Harap masukkan teks terlebih dahulu." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:414 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:417 msgid "Generating..." msgstr "Sedang memproses..." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:421 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:424 msgid "Generating speech, please wait..." msgstr "Sedang menghasilkan audio, harap tunggu..." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:429 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:433 #, python-brace-format msgid "Failed to initialize Google GenAI client: {error}" msgstr "Gagal menginisialisasi klien Google Genai: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:440 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:444 msgid "Failed to generate audio." msgstr "Gagal menghasilkan audio." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:442 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:446 msgid "Generation complete." msgstr "Selesai membuat audio." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:512 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:520 msgid "An error occurred during generation." msgstr "Terjadi kesalahan selama menghasilkan audio." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:516 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:524 #, python-brace-format msgid "An unexpected error occurred: {error}" msgstr "Terjadi kesalahan yang tidak terduga: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:585 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:595 msgid "No inline audio data returned by model." msgstr "Tidak ada data audio inline yang dikembalikan oleh model." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:608 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:618 #, python-brace-format msgid "Failed to generate speech: {error}" msgstr "Gagal menghasilkan ucapan: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:627 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:637 msgid "Save Audio File" msgstr "Simpan file audio" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:628 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:638 msgid "WAV files (*.wav)|*.wav|MP3 files (*.mp3)|*.mp3" msgstr "Berkas WAV (*.wav)|*.wav|Berkas Mp3 (*.mp3)|*.mp3" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:640 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:650 #, python-brace-format msgid "Audio saved to {path}" msgstr "Audio disimpan ke {path}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:641 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:651 msgid "Success" msgstr "Success" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:647 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:657 #, python-brace-format msgid "Failed to save audio: {error}" msgstr "Gagal menyimpan audio: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:662 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:672 msgid "Sample not available" msgstr "Suara sampel tidak tersedia" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:667 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:677 msgid "Playing voice sample" msgstr "Memainkan sampel suara" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:672 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:682 msgid "Failed to play sample" msgstr "Gagal memainkan sampel audio" #. Translators: Label for the input field where user enters their Gemini API Key. -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:36 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:38 msgid "&Gemini API Key:" msgstr "& Kunci API Gemini:" #. Translators: Checkbox to toggle visibility of the API key (show/hide characters). -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:50 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:52 msgid "Show API Key" msgstr "Tampilkan kunci API" #. Add the row to the main settings sizer #. Set initial state #. Translators: Button starting a process to help user get an API key (opens a website). -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:58 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:60 msgid "&How to get API Key..." msgstr "&Cara Mendapatkan Kunci API..." #. Reinstall libraries button #. Translators: Button to force a reinstallation of external dependencies (Python libraries). -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:64 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:66 msgid "&Reinstall Libraries" msgstr "&Instal ulang Librarys" -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:85 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:87 msgid "" "This will delete the existing library and restart NVDA to redownload it.\n" "Are you sure?" @@ -544,7 +557,7 @@ msgstr "" "mengunduhnya ulang.\n" "Apakah kamu yakin?" -#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:112 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:114 msgid "" "Library removed successfully. NVDA will now restart to download the latest " "version." @@ -605,17 +618,29 @@ msgstr "" #: buildVars.py:18 msgid "" -"- Stability: Restored previous dependency handling to resolve crashes (pyo3 " -"panic).\n" -"- Localization: Fixed translation issues for Interface and Settings " -"dialogs.\n" -"- Fix: Resolved SSL Certificate path error.\n" +"- Talk With AI: Added optional session memory and a clear-memory control.\n" +"- Talk With AI: Improved stream stability with reconnect backoff/retry and " +"adaptive buffering.\n" +"- Documentation: Added Spanish-language documentation.\n" msgstr "" -"- Stabilitas: Memulihkan penanganan ketergantungan sebelumnya untuk " -"mengatasi kerusakan (panik pyo3).\n" -"- Lokalisasi: Memperbaiki masalah terjemahan untuk dialog Antarmuka dan " -"Pengaturan.\n" -"- Perbaiki: Kesalahan jalur Sertifikat SSL teratasi.\n" +"- Bicara Dengan AI: Menambahkan memori sesi opsional dan kontrol memori yang " +"jelas.\n" +"- Bicara Dengan AI: Peningkatan stabilitas streaming dengan koneksi ulang " +"backoff/coba lagi dan buffering adaptif.\n" +"- Dokumentasi: Menambahkan dokumentasi berbahasa Spanyol.\n" + +#~ msgid "" +#~ "- Stability: Restored previous dependency handling to resolve crashes " +#~ "(pyo3 panic).\n" +#~ "- Localization: Fixed translation issues for Interface and Settings " +#~ "dialogs.\n" +#~ "- Fix: Resolved SSL Certificate path error.\n" +#~ msgstr "" +#~ "- Stabilitas: Memulihkan penanganan ketergantungan sebelumnya untuk " +#~ "mengatasi kerusakan (panik pyo3).\n" +#~ "- Lokalisasi: Memperbaiki masalah terjemahan untuk dialog Antarmuka dan " +#~ "Pengaturan.\n" +#~ "- Perbaiki: Kesalahan jalur Sertifikat SSL teratasi.\n" #~ msgid "" #~ "- Code Refactoring: Complies with NVDA coding standards (Tabs, " diff --git a/addon/locale/ru/LC_MESSAGES/nvda.po b/addon/locale/ru/LC_MESSAGES/nvda.po index 04d209f..9be63d7 100644 --- a/addon/locale/ru/LC_MESSAGES/nvda.po +++ b/addon/locale/ru/LC_MESSAGES/nvda.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: NativeSpeechGeneration\n" +"Project-Id-Version: 'NativeSpeechGeneration' '1.5.6'\n" "Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n" -"POT-Creation-Date: 2026-02-07 13:00+0700\n" -"PO-Revision-Date: 2026-02-10 07:49+0700\n" +"POT-Creation-Date: 2026-02-20 16:58+0700\n" +"PO-Revision-Date: 2026-02-20 17:17+0700\n" "Last-Translator: nvda.ru\n" "Language-Team: nvda.ru\n" "Language: ru_RU\n" @@ -50,20 +50,20 @@ msgstr "" #: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:97 #: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:153 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:217 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:218 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:153 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:344 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:361 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:381 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:392 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:400 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:409 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:431 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:521 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:590 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:613 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:652 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:233 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:234 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:146 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:346 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:363 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:383 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:394 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:402 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:411 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:434 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:525 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:596 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:619 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:658 #: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:126 msgid "Error" msgstr "Ошибка" @@ -125,119 +125,133 @@ msgid "Missing Dependencies" msgstr "Отсутствующие зависимости" #. Translators: Title of the dialog for the "Talk With AI" feature (REAL-TIME conversation). -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:53 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:51 msgid "Talk With AI" msgstr "Разговор с ИИ" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:83 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:87 msgid "PyAudio library is not installed. This feature requires PyAudio." msgstr "Библиотека PyAudio не установлена. Для этой функции требуется PyAudio." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:87 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:91 msgid "Google GenAI library is not installed." msgstr "Библиотека Google GenAI не установлена." #. 1. Status Area #. Translators: Label for the status area showing connection state. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:124 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:129 msgid "Status" msgstr "Статус" #. Translators: Initial status message when the dialog opens. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:127 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:132 msgid "Ready to Connect" msgstr "Готово к подключению" #. 2. Controls Area -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:132 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:137 msgid "Controls" msgstr "Управление" #. Translators: Button to start the voice conversation. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:138 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:143 msgid "Start Conversation" msgstr "Начать разговор" #. Translators: Button to stop the voice conversation. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:141 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:146 msgid "Stop Conversation" msgstr "Остановить разговор" #. Mic Toggle #. Translators: Toggle button label indicating microphone is ON. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:151 -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:222 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:156 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:238 msgid "Microphone: ON" msgstr "Микрофон: ВКЛ" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:161 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:166 msgid "Microphone:" msgstr "Микрофон:" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:172 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:177 msgid "Speaker:" msgstr "Динамик:" #. Google Search Checkbox #. Translators: Checkbox to enable "Grounding", allowing the AI to search Google for answers. -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:185 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:190 msgid "Grounding with Google Search" msgstr "Привязка к Google Поиску" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:191 +#. Translators: Checkbox to enable temporary conversation memory during this dialog session. +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:195 +msgid "Use session memory" +msgstr "" + +#. Translators: Button to clear temporary conversation memory for the current dialog session. +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:201 +msgid "Clear memory now" +msgstr "" + +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:207 msgid "Volume:" msgstr "Громкость:" #. 3. Info Area (Voice only) #. Translators: Label for the selected voice -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:203 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:219 msgid "Voice: " msgstr "Голос: " -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:213 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:229 msgid "Status: " msgstr "Статус: " -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:222 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:238 msgid "Microphone: OFF" msgstr "Микрофон: ВЫКЛ" -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:259 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:256 +msgid "Memory cleared" +msgstr "" + +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:337 msgid "Connecting..." msgstr "Подключение..." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:267 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:345 msgid "Disconnecting..." msgstr "Отключение..." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:550 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:656 msgid "Connected" msgstr "Подключено" -#. Only play end sound if we are giving up (session not active) -#. or just notify user of retry -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:588 -msgid "Connection Lost. Retrying..." +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:698 +#, fuzzy, python-brace-format +#| msgid "Connection Lost. Retrying..." +msgid "Connection lost. Retrying in {seconds:.1f}s" msgstr "Соединение потеряно. Повторная попытка..." -#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:638 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:752 msgid "Ready" msgstr "Готово" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:69 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:122 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:61 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:115 msgid "Open the Native Speech Generation dialog" msgstr "Открыть диалог Нативной генерации речи" #. Translators: Title of the settings panel in NVDA preferences. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:70 -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:123 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:62 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:116 #: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:29 #: buildVars.py:6 msgid "Native Speech Generation" msgstr "Нативная генерация речи" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:77 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:69 msgid "" "Native Speech Generation is installing dependencies. Please restart NVDA for " "the changes to take effect." @@ -246,22 +260,22 @@ msgstr "" "NVDA, чтобы изменения вступили в силу." #. Translators: Title of the information dialog recommending a restart. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:80 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:73 #: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:115 msgid "Restart Required" msgstr "Требуется перезагрузка" #. Translators: Name of the add-on in the NVDA Tools menu. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:115 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:108 msgid "&Native Speech Generation" msgstr "&Нативная генерация речи" #. Translators: Tooltip or description for the menu item. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:117 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:110 msgid "Generate speech using Gemini TTS" msgstr "Генерация речи с использованием Gemini TTS" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:137 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:130 msgid "" "The Native Speech Generation add-on is already open. Please close the dialog " "before opening it again." @@ -270,11 +284,11 @@ msgstr "" "диалог перед повторным открытием." #. Translators: Title of warning dialog when user tries to open the add-on twice. -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:140 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:133 msgid "Add-on Already Running" msgstr "Дополнение уже запущено" -#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:152 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:145 #, python-brace-format msgid "Failed to open Native Speech Generation dialog: {error}" msgstr "Не удалось открыть диалог «Нативная генерация речи»: {error}" @@ -332,7 +346,7 @@ msgstr "Температура:" #. Translators: Button to start generating the speech audio. #: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:147 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:529 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:533 msgid "&Generate Speech" msgstr "&Сгенерировать речь" @@ -382,7 +396,7 @@ msgid "Speaker 1 Name:" msgstr "Имя говорящего 1:" #: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:219 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:467 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:471 msgid "Speaker1" msgstr "Говорящий 1" @@ -396,15 +410,15 @@ msgid "Speaker 2 Name:" msgstr "Имя говорящего 2:" #: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:235 -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:468 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:472 msgid "Speaker2" msgstr "Говорящий 2" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:343 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:345 msgid "Talk With AI module is missing." msgstr "Модуль «Разговор с ИИ» отсутствует." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:353 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:355 msgid "" "Talk With AI currently does not support multi-speaker mode. Please select " "Single-speaker." @@ -412,104 +426,104 @@ msgstr "" "Режим «Разговор с ИИ» в настоящее время не поддерживает несколько говорящих. " "Пожалуйста, выберите «Один говорящий»." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:355 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:357 msgid "Feature Limitation" msgstr "Ограничение функции" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:361 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:363 msgid "No GEMINI_API_KEY configured." msgstr "" "Ключ GEMINI_API_KEY не настроен. Установите его в настройках NVDA в разделе " "NativeSpeechGeneration." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:380 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:382 #, python-brace-format msgid "Failed to open Talk With AI: {error}" msgstr "Не удалось открыть «Разговор с ИИ»: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:391 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:393 msgid "google-genai library not installed. Please restart NVDA." msgstr "" "библиотека google-genai не установлена. Пожалуйста, перезагрузите NVDA." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:399 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:401 msgid "No GEMINI_API_KEY configured. Set it in NVDA settings." msgstr "Ключ GEMINI_API_KEY не настроен. Установите его в настройках NVDA." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:408 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:410 msgid "Please enter text to generate." msgstr "Пожалуйста, введите текст для генерации." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:415 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:417 msgid "Generating..." msgstr "Генерация..." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:422 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:424 msgid "Generating speech, please wait..." msgstr "Идёт генерация речи, пожалуйста, подождите..." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:430 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:433 #, python-brace-format msgid "Failed to initialize Google GenAI client: {error}" msgstr "Не удалось инициализировать клиент Google GenAI: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:441 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:444 msgid "Failed to generate audio." msgstr "Не удалось сгенерировать аудио." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:443 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:446 msgid "Generation complete." msgstr "Генерация завершена." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:516 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:520 msgid "An error occurred during generation." msgstr "Во время генерации произошла ошибка." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:520 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:524 #, python-brace-format msgid "An unexpected error occurred: {error}" msgstr "Произошла непредвиденная ошибка: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:589 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:595 msgid "No inline audio data returned by model." msgstr "Модель не вернула встроенные аудиоданные." -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:612 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:618 #, python-brace-format msgid "Failed to generate speech: {error}" msgstr "Не удалось сгенерировать речь: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:631 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:637 msgid "Save Audio File" msgstr "Сохранить аудиофайл" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:632 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:638 msgid "WAV files (*.wav)|*.wav|MP3 files (*.mp3)|*.mp3" msgstr "Файлы WAV (*.wav)|*.wav|Файлы MP3 (*.mp3)|*.mp3" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:644 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:650 #, python-brace-format msgid "Audio saved to {path}" msgstr "Аудио сохранено в {path}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:645 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:651 msgid "Success" msgstr "Успешно" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:651 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:657 #, python-brace-format msgid "Failed to save audio: {error}" msgstr "Не удалось сохранить аудио: {error}" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:666 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:672 msgid "Sample not available" msgstr "Образец недоступен" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:671 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:677 msgid "Playing voice sample" msgstr "Воспроизведение образца голоса" -#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:676 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:682 msgid "Failed to play sample" msgstr "Не удалось воспроизвести образец" @@ -603,17 +617,24 @@ msgstr "" #: buildVars.py:18 msgid "" -"- Stability: Restored previous dependency handling to resolve crashes (pyo3 " -"panic).\n" -"- Localization: Fixed translation issues for Interface and Settings " -"dialogs.\n" -"- Fix: Resolved SSL Certificate path error.\n" +"- Talk With AI: Added optional session memory and a clear-memory control.\n" +"- Talk With AI: Improved stream stability with reconnect backoff/retry and " +"adaptive buffering.\n" +"- Documentation: Added Spanish-language documentation.\n" msgstr "" -"- Стабильность: Восстановлена прежняя обработка зависимостей для устранения " -"сбоев (паника pyo3).\n" -"- Локализация: Исправлены проблемы перевода в диалогах Интерфейса и " -"Настроек.\n" -"- Исправление: Устранена ошибка пути к SSL-сертификату.\n" + +#~ msgid "" +#~ "- Stability: Restored previous dependency handling to resolve crashes " +#~ "(pyo3 panic).\n" +#~ "- Localization: Fixed translation issues for Interface and Settings " +#~ "dialogs.\n" +#~ "- Fix: Resolved SSL Certificate path error.\n" +#~ msgstr "" +#~ "- Стабильность: Восстановлена прежняя обработка зависимостей для " +#~ "устранения сбоев (паника pyo3).\n" +#~ "- Локализация: Исправлены проблемы перевода в диалогах Интерфейса и " +#~ "Настроек.\n" +#~ "- Исправление: Устранена ошибка пути к SSL-сертификату.\n" #~ msgid "Audio generated, but failed to play automatically: {error}" #~ msgstr "" diff --git a/addon/locale/uk/LC_MESSAGES/nvda.po b/addon/locale/uk/LC_MESSAGES/nvda.po index 6546443..0536df6 100644 --- a/addon/locale/uk/LC_MESSAGES/nvda.po +++ b/addon/locale/uk/LC_MESSAGES/nvda.po @@ -1,9 +1,9 @@ msgid "" msgstr "" -"Project-Id-Version: \n" -"Report-Msgid-Bugs-To: nvda-translations@groups.io\n" -"POT-Creation-Date: 2026-01-29 11:41+0000\n" -"PO-Revision-Date: 2026-01-30 22:49+0200\n" +"Project-Id-Version: 'NativeSpeechGeneration' '1.5.6'\n" +"Report-Msgid-Bugs-To: 'nvda-translations@groups.io'\n" +"POT-Creation-Date: 2026-02-20 16:58+0700\n" +"PO-Revision-Date: 2026-02-20 17:18+0700\n" "Last-Translator: \n" "Language-Team: \n" "Language: uk_UA\n" @@ -13,225 +13,239 @@ msgstr "" "X-Generator: Poedit 3.8\n" "X-Poedit-Basepath: .\n" +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:57 +msgid "Downloading libraries..." +msgstr "Завантаження бібліотек..." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:71 +msgid "Downloading..." +msgstr "Завантаження..." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:76 +msgid "Extracting libraries..." +msgstr "Видобування бібліотек..." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:84 +msgid "Extraction complete." +msgstr "Видобування завершено." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:95 +#, python-brace-format +msgid "" +"Failed to download or extract required libraries. The add-on might not work " +"correctly.\n" +"\n" +"Error: {error}" +msgstr "" +"Не вдалося завантажити або видобути необхідні бібліотеки. Додаток може " +"працювати некоректно.\n" +"\n" +"Помилка: {error}" + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:97 +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:153 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:233 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:234 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:146 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:346 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:363 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:383 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:394 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:402 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:411 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:434 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:525 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:596 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:619 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:658 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:126 +msgid "Error" +msgstr "Помилка" + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:117 +msgid "Installing Dependencies" +msgstr "Встановлення залежностей" + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:118 +msgid "Checking for required libraries..." +msgstr "Перевірка необхідних бібліотек..." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:127 +msgid "Installation complete!" +msgstr "Встановлення завершено!" + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:145 +msgid "" +"The Native Speech Generation libraries have been successfully installed/" +"updated.\n" +"\n" +"Please restart NVDA for the changes to take effect." +msgstr "" +"Бібліотеки Генерації природного мовлення успішно встановлені/оновлені.\n" +"\n" +"Будь ласка, перезапустіть NVDA, щоб зміни набули чинності." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:147 +msgid "Installation Complete" +msgstr "Встановлення завершено" + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:152 +msgid "Library installation failed. Please check the log." +msgstr "Помилка встановлення бібліотеки. Будь ласка, перевірте журнал." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:164 +msgid "" +"Are you sure you want to reinstall the libraries? This will redownload the " +"dependencies and require an NVDA restart." +msgstr "" +"Ви впевнені, що бажаєте перевстановити бібліотеки? Це призведе до повторного " +"завантаження залежностей і потребує перезапуску NVDA." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:166 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:88 +msgid "Confirm Reinstall" +msgstr "Підтвердити перевстановлення" + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:168 +msgid "" +"Required libraries for Native Speech Generation are missing. Click OK to " +"download them." +msgstr "" +"Відсутні необхідні бібліотеки для генерації природного мовлення. Натисніть " +"OK, щоб завантажити їх." + +#: addon\globalPlugins\NativeSpeechGeneration\lib_updater.py:169 +msgid "Missing Dependencies" +msgstr "Відсутні залежності" + #. Translators: Title of the dialog for the "Talk With AI" feature (REAL-TIME conversation). -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:53 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:51 msgid "Talk With AI" msgstr "Розмова з ШІ" -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:83 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:87 msgid "PyAudio library is not installed. This feature requires PyAudio." msgstr "Бібліотека PyAudio не встановлена. Для цієї функції потрібен PyAudio." -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:87 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:91 msgid "Google GenAI library is not installed." msgstr "Бібліотека Google GenAI не встановлена." #. 1. Status Area #. Translators: Label for the status area showing connection state. -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:124 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:129 msgid "Status" msgstr "Статус" #. Translators: Initial status message when the dialog opens. -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:127 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:132 msgid "Ready to Connect" msgstr "Готовий до підключення" #. 2. Controls Area -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:132 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:137 msgid "Controls" msgstr "Керування" #. Translators: Button to start the voice conversation. -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:138 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:143 msgid "Start Conversation" msgstr "Розпочати розмову" #. Translators: Button to stop the voice conversation. -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:141 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:146 msgid "Stop Conversation" msgstr "Зупинити розмову" #. Mic Toggle #. Translators: Toggle button label indicating microphone is ON. -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:151 -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:222 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:156 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:238 msgid "Microphone: ON" msgstr "Мікрофон: УВІМК" -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:161 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:166 msgid "Microphone:" msgstr "Мікрофон:" -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:172 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:177 msgid "Speaker:" msgstr "Голос:" #. Google Search Checkbox #. Translators: Checkbox to enable "Grounding", allowing the AI to search Google for answers. -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:185 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:190 msgid "Grounding with Google Search" msgstr "Перевірка за допомогою пошуку Google" -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:191 +#. Translators: Checkbox to enable temporary conversation memory during this dialog session. +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:195 +msgid "Use session memory" +msgstr "" + +#. Translators: Button to clear temporary conversation memory for the current dialog session. +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:201 +msgid "Clear memory now" +msgstr "" + +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:207 msgid "Volume:" msgstr "Гучність:" #. 3. Info Area (Voice only) #. Translators: Label for the selected voice -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:203 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:219 msgid "Voice: " msgstr "Голос: " -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:213 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:229 msgid "Status: " msgstr "Статус: " -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:217 -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:218 -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:97 -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:153 -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:153 -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:126 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:344 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:361 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:381 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:392 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:400 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:409 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:431 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:518 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:587 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:610 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:649 -msgid "Error" -msgstr "Помилка" - -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:222 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:238 msgid "Microphone: OFF" msgstr "Мікрофон: ВИМК" -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:259 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:256 +msgid "Memory cleared" +msgstr "" + +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:337 msgid "Connecting..." msgstr "Підключення..." -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:267 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:345 msgid "Disconnecting..." msgstr "Відключення..." -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:550 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:656 msgid "Connected" msgstr "З'єднано" -#. Only play end sound if we are giving up (session not active) -#. or just notify user of retry -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:588 -msgid "Connection Lost. Retrying..." +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:698 +#, fuzzy, python-brace-format +#| msgid "Connection Lost. Retrying..." +msgid "Connection lost. Retrying in {seconds:.1f}s" msgstr "З’єднання втрачено. Повторна спроба..." -#: addon/globalPlugins/NativeSpeechGeneration/talkWithAI.py:638 +#: addon\globalPlugins\NativeSpeechGeneration\talkWithAI.py:752 msgid "Ready" msgstr "Готово" -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:57 -msgid "Downloading libraries..." -msgstr "Завантаження бібліотек..." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:71 -msgid "Downloading..." -msgstr "Завантаження..." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:76 -msgid "Extracting libraries..." -msgstr "Видобування бібліотек..." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:84 -msgid "Extraction complete." -msgstr "Видобування завершено." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:95 -#, python-brace-format -msgid "" -"Failed to download or extract required libraries. The add-on might not work " -"correctly.\n" -"\n" -"Error: {error}" -msgstr "" -"Не вдалося завантажити або видобути необхідні бібліотеки. Додаток може " -"працювати некоректно.\n" -"\n" -"Помилка: {error}" - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:117 -msgid "Installing Dependencies" -msgstr "Встановлення залежностей" - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:118 -msgid "Checking for required libraries..." -msgstr "Перевірка необхідних бібліотек..." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:127 -msgid "Installation complete!" -msgstr "Встановлення завершено!" - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:145 -msgid "" -"The Native Speech Generation libraries have been successfully installed/" -"updated.\n" -"\n" -"Please restart NVDA for the changes to take effect." -msgstr "" -"Бібліотеки Генерації природного мовлення успішно встановлені/оновлені.\n" -"\n" -"Будь ласка, перезапустіть NVDA, щоб зміни набули чинності." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:147 -msgid "Installation Complete" -msgstr "Встановлення завершено" - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:152 -msgid "Library installation failed. Please check the log." -msgstr "Помилка встановлення бібліотеки. Будь ласка, перевірте журнал." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:164 -msgid "" -"Are you sure you want to reinstall the libraries? This will redownload the " -"dependencies and require an NVDA restart." -msgstr "" -"Ви впевнені, що бажаєте перевстановити бібліотеки? Це призведе до повторного " -"завантаження залежностей і потребує перезапуску NVDA." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:166 -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:88 -msgid "Confirm Reinstall" -msgstr "Підтвердити перевстановлення" - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:168 -msgid "" -"Required libraries for Native Speech Generation are missing. Click OK to " -"download them." -msgstr "" -"Відсутні необхідні бібліотеки для генерації природного мовлення. Натисніть " -"OK, щоб завантажити їх." - -#: addon/globalPlugins/NativeSpeechGeneration/lib_updater.py:169 -msgid "Missing Dependencies" -msgstr "Відсутні залежності" - -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:69 -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:122 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:61 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:115 msgid "Open the Native Speech Generation dialog" msgstr "Відкриває діалог генерації природного мовлення" #. Translators: Title of the settings panel in NVDA preferences. -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:70 -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:123 -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:29 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:62 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:116 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:29 #: buildVars.py:6 msgid "Native Speech Generation" msgstr "Генерація природного мовлення" -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:77 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:69 msgid "" "Native Speech Generation is installing dependencies. Please restart NVDA for " "the changes to take effect." @@ -240,22 +254,22 @@ msgstr "" "зміни набули чинності." #. Translators: Title of the information dialog recommending a restart. -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:80 -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:115 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:73 +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:115 msgid "Restart Required" msgstr "Потрібен перезапуск" #. Translators: Name of the add-on in the NVDA Tools menu. -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:115 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:108 msgid "&Native Speech Generation" msgstr "&Генерація природного мовлення" #. Translators: Tooltip or description for the menu item. -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:117 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:110 msgid "Generate speech using Gemini TTS" msgstr "Генерувати мовлення за допомогою Gemini TTS" -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:137 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:130 msgid "" "The Native Speech Generation add-on is already open. Please close the dialog " "before opening it again." @@ -264,181 +278,141 @@ msgstr "" "перш ніж відкривати його знову." #. Translators: Title of warning dialog when user tries to open the add-on twice. -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:140 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:133 msgid "Add-on Already Running" msgstr "Додаток вже запущено" -#: addon/globalPlugins/NativeSpeechGeneration/__init__.py:152 +#: addon\globalPlugins\NativeSpeechGeneration\__init__.py:145 #, python-brace-format msgid "Failed to open Native Speech Generation dialog: {error}" msgstr "Не вдалося відкрити діалог«Генерація природного мовлення»: {error}" -#. Translators: Label for the input field where user enters their Gemini API Key. -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:38 -msgid "&Gemini API Key:" -msgstr "&Ключ API Gemini:" - -#. Translators: Checkbox to toggle visibility of the API key (show/hide characters). -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:52 -msgid "Show API Key" -msgstr "Показати ключ API" - -#. Add the row to the main settings sizer -#. Set initial state -#. Translators: Button starting a process to help user get an API key (opens a website). -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:60 -msgid "&How to get API Key..." -msgstr "&Як отримати ключ API ..." - -#. Reinstall libraries button -#. Translators: Button to force a reinstallation of external dependencies (Python libraries). -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:66 -msgid "&Reinstall Libraries" -msgstr "&Перевстановити бібліотеки" - -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:87 -msgid "" -"This will delete the existing library and restart NVDA to redownload it.\n" -"Are you sure?" -msgstr "" -"Це призведе до видалення існуючої бібліотеки та перезапуску NVDA для її " -"повторного завантаження.\n" -"Ви впевнені?" - -#: addon/globalPlugins/NativeSpeechGeneration/interface/settings.py:114 -msgid "" -"Library removed successfully. NVDA will now restart to download the latest " -"version." -msgstr "" -"Бібліотеку успішно видалено. Тепер NVDA перезапуститься, щоб завантажити " -"останню версію." - #. Translators: The title of the main dialog window for generating speech. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:48 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:48 msgid "Native Speech Generation (Gemini TTS)" msgstr "Генерація природного мовлення (Gemini TTS)" #. Text Input #. Translators: Label for the text area where user inputs text to be converted to speech. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:73 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:73 msgid "&Type text to convert here:" msgstr "&Введіть тут текст для перетворення:" #. Style Input #. Translators: Label for optional instructions on how the speech should be spoken (e.g. "Happy", "Sad"). -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:80 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:80 msgid "&Style instructions (optional):" msgstr "&Інструкції щодо стилю (за бажанням):" #. Translators: Label for selecting the AI model to use for generation. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:88 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:88 msgid "Select &Model:" msgstr "Виберіть модель:" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:89 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:89 msgid "Flash (Standard Quality)" msgstr "Flash (стандартна якість)" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:89 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:89 msgid "Pro (High Quality)" msgstr "Pro (висока якість)" #. Translators: Radio button to select single speaker mode. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:96 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:96 msgid "Single-speaker" msgstr "Одномовний" #. Translators: Radio button to select multi-speaker mode. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:98 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:98 msgid "Multi-speaker (2)" msgstr "Багатомовний (2)" #. Settings Toggle #. Translators: Checkbox to show advanced settings like Temperature. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:108 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:108 msgid "Advanced Settings (&Temperature)" msgstr "Розширені налаштування (&тембр)" #. Translators: Label for the temperature slider which controls creativity of the AI. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:119 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:119 msgid "Temperature:" msgstr "Тембр:" #. Translators: Button to start generating the speech audio. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:147 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:526 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:147 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:533 msgid "&Generate Speech" msgstr "&Генерувати мовлення" #. Translators: Button to play the generated audio. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:152 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:152 msgid "&Play" msgstr "&Грати" #. Translators: Button to save the generated audio to a file. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:158 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:158 msgid "Save &Audio" msgstr "Зберегти &аудіо" #. Talk With AI Button #. Translators: Button to open the real-time conversation dialog. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:167 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:167 msgid "Talk With &AI" msgstr "Розмова з &ШІ" #. Translators: Button to open settings specifically for configuring the API key. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:174 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:174 msgid "API Key Settings" msgstr "Налаштування ключа API" #. Translators: Button that opens a web browser to view available voices in Google AI Studio. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:177 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:177 msgid "View voices in AI Studio" msgstr "Переглянути голоси в AI Studio" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:183 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:183 msgid "&Close" msgstr "&Закрити" #. Translators: Label for selecting a voice in single speaker mode. -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:201 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:201 msgid "Select &Voice:" msgstr "Вибрати & Голос:" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:202 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:221 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:237 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:202 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:221 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:237 msgid "Loading voices..." msgstr "Завантаження голосів ..." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:218 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:218 msgid "Speaker 1 Name:" msgstr "Голос 1 Ім'я:" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:219 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:464 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:219 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:471 msgid "Speaker1" msgstr "Голос 1" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:220 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:236 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:220 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:236 msgid "Voice:" msgstr "Голос:" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:234 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:234 msgid "Speaker 2 Name:" msgstr "Голос2 Ім'я:" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:235 -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:465 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:235 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:472 msgid "Speaker2" msgstr "Голос 2" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:343 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:345 msgid "Talk With AI module is missing." msgstr "Модуль «Розмова з ШІ» відсутній." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:353 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:355 msgid "" "Talk With AI currently does not support multi-speaker mode. Please select " "Single-speaker." @@ -446,104 +420,144 @@ msgstr "" "Зараз Розмова з ШІ не підтримує режим декількох співрозмовників. Будь ласка, " "оберіть режим одного співрозмовника." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:355 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:357 msgid "Feature Limitation" msgstr "Обмеження функцій" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:361 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:363 msgid "No GEMINI_API_KEY configured." msgstr "Не налаштовано ключ_GEMINI_API." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:380 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:382 #, python-brace-format msgid "Failed to open Talk With AI: {error}" msgstr "Не вдалося відкрити Розмову з ШІ: {error}" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:391 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:393 msgid "google-genai library not installed. Please restart NVDA." msgstr "бібліотека google-genai не встановлена. Перезапустіть NVDA." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:399 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:401 msgid "No GEMINI_API_KEY configured. Set it in NVDA settings." msgstr "Ключ_GEMINI_API не налаштовано. Встановіть його в налаштуваннях NVDA." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:408 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:410 msgid "Please enter text to generate." msgstr "Будь ласка, введіть текст для генерації." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:415 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:417 msgid "Generating..." msgstr "Генерувати..." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:422 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:424 msgid "Generating speech, please wait..." msgstr "Генерація мовлення, будь ласка, зачекайте..." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:430 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:433 #, python-brace-format msgid "Failed to initialize Google GenAI client: {error}" msgstr "Не вдалося ініціалізувати клієнт Google GenAI: {error}" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:441 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:444 msgid "Failed to generate audio." msgstr "Не вдалося створити аудіо." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:443 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:446 msgid "Generation complete." msgstr "Генерація завершена." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:513 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:520 msgid "An error occurred during generation." msgstr "Під час генерації сталася помилка." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:517 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:524 #, python-brace-format msgid "An unexpected error occurred: {error}" msgstr "Сталася несподівана помилка: {error}" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:586 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:595 msgid "No inline audio data returned by model." msgstr "Модель не повертає вбудованих аудіоданих." -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:609 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:618 #, python-brace-format msgid "Failed to generate speech: {error}" msgstr "Не вдалося згенерувати мовлення: {error}" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:628 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:637 msgid "Save Audio File" msgstr "Зберегти аудіофайл" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:629 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:638 msgid "WAV files (*.wav)|*.wav|MP3 files (*.mp3)|*.mp3" msgstr "Файли WAV (*.wav)|*.wav|Файли MP3 (*.mp3)|*.mp3" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:641 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:650 #, python-brace-format msgid "Audio saved to {path}" msgstr "Аудіо збережено в {path}" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:642 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:651 msgid "Success" msgstr "Успіх" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:648 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:657 #, python-brace-format msgid "Failed to save audio: {error}" msgstr "Не вдалося зберегти аудіо: {error}" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:663 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:672 msgid "Sample not available" msgstr "Зразок недоступний" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:668 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:677 msgid "Playing voice sample" msgstr "Відтворення зразка голосу" -#: addon/globalPlugins/NativeSpeechGeneration/interface/generation_dialog.py:673 +#: addon\globalPlugins\NativeSpeechGeneration\interface\generation_dialog.py:682 msgid "Failed to play sample" msgstr "Не вдалося відтворити зразок" +#. Translators: Label for the input field where user enters their Gemini API Key. +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:38 +msgid "&Gemini API Key:" +msgstr "&Ключ API Gemini:" + +#. Translators: Checkbox to toggle visibility of the API key (show/hide characters). +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:52 +msgid "Show API Key" +msgstr "Показати ключ API" + +#. Add the row to the main settings sizer +#. Set initial state +#. Translators: Button starting a process to help user get an API key (opens a website). +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:60 +msgid "&How to get API Key..." +msgstr "&Як отримати ключ API ..." + +#. Reinstall libraries button +#. Translators: Button to force a reinstallation of external dependencies (Python libraries). +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:66 +msgid "&Reinstall Libraries" +msgstr "&Перевстановити бібліотеки" + +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:87 +msgid "" +"This will delete the existing library and restart NVDA to redownload it.\n" +"Are you sure?" +msgstr "" +"Це призведе до видалення існуючої бібліотеки та перезапуску NVDA для її " +"повторного завантаження.\n" +"Ви впевнені?" + +#: addon\globalPlugins\NativeSpeechGeneration\interface\settings.py:114 +msgid "" +"Library removed successfully. NVDA will now restart to download the latest " +"version." +msgstr "" +"Бібліотеку успішно видалено. Тепер NVDA перезапуститься, щоб завантажити " +"останню версію." + #: buildVars.py:7 msgid "" "Harness the power of Google's state-of-the-art Gemini AI for high-quality " @@ -594,11 +608,10 @@ msgstr "" #: buildVars.py:18 msgid "" -"- Stability: Restored previous dependency handling to resolve crashes (pyo3 " -"panic).\n" -"- Localization: Fixed translation issues for Interface and Settings " -"dialogs.\n" -"- Fix: Resolved SSL Certificate path error.\n" +"- Talk With AI: Added optional session memory and a clear-memory control.\n" +"- Talk With AI: Improved stream stability with reconnect backoff/retry and " +"adaptive buffering.\n" +"- Documentation: Added Spanish-language documentation.\n" msgstr "" #, python-brace-format diff --git a/buildVars.py b/buildVars.py index 783d365..cf76b6d 100644 --- a/buildVars.py +++ b/buildVars.py @@ -14,17 +14,17 @@ - Seamless Workflow: The add-on provides instant audio playback upon generation and allows you to save the resulting .wav file for later use. To get started, obtain a Gemini API key from Google AI Studio and enter it in the add-on's settings panel, found under NVDA's Tools menu."""), - addon_version="1.5.5", - addon_changelog=_("""- Stability: Restored previous dependency handling to resolve crashes (pyo3 panic). -- Localization: Fixed translation issues for Interface and Settings dialogs. -- Fix: Resolved SSL Certificate path error. + addon_version="1.5.6", + addon_changelog=_("""- Talk With AI: Added optional session memory and a clear-memory control. +- Talk With AI: Improved stream stability with reconnect backoff/retry and adaptive buffering. +- Documentation: Added Spanish-language documentation. """), addon_author="Muhammad ", addon_url="https://github.com/muhammadGagah/native-speech-generation/", addon_sourceURL="https://github.com/muhammadGagah/native-speech-generation/", addon_docFileName="readme.html", addon_minimumNVDAVersion="2024.1", - addon_lastTestedNVDAVersion="2025.3.2", + addon_lastTestedNVDAVersion="2025.3.3", addon_updateChannel=None, addon_license="GPL-2.0", addon_licenseURL="https://www.gnu.org/licenses/gpl-2.0.html", diff --git a/changelog.md b/changelog.md index 595dba1..ca6b39c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,9 @@ # Changelog -## version 1.5.4 +## version 1.5.6 -- Stability: Restored previous dependency handling to resolve crashes (pyo3 panic) caused by aggressive module unloading. -- Localization: Fixed missing translations for Interface and Settings dialogs by ensuring all source files are included in the build process. -- Fix: Resolved "FileNotFoundError" for SSL certificates by patching `certifi` to locate the certificate file correctly within the add-on's directory. +- Talk With AI: Added optional session memory to keep temporary conversation context during an active voice session. +- Talk With AI: Added a clear-memory control to reset temporary session context on demand. +- Talk With AI: Improved streaming stability with better reconnection handling (backoff + retry) and adaptive audio buffering. +- UI: Simplified Generate Speech status behavior back to the standard `Generating...` flow. +- Documentation: Added Spanish-language documentation. diff --git a/readme.md b/readme.md index b7fdbb1..b80a3a1 100644 --- a/readme.md +++ b/readme.md @@ -58,6 +58,9 @@ This add-on is designed for smooth workflows, accessibility-first interaction, a * **Grounding with Google Search**: Enable the AI to access real-time information from the web during your chat. * **Interruptible**: You can interrupt the AI at any time by speaking or pressing "Stop Conversation". * **Customizable**: Uses your selected voice and style instructions. +* **Session Memory (Optional)**: Keep temporary conversation context during the current Talk With AI session for more coherent follow-up responses. +* **Clear Memory Control**: Clear temporary session memory before starting a conversation (or after stopping). +* **More Stable Streaming**: Improved reconnection behavior (backoff + retry) and adaptive audio buffering for better resilience on unstable networks. --- @@ -162,6 +165,8 @@ Experience a natural, two-way voice conversation with Gemini. * **Stop Conversation**: Ends the session. * **Grounding with Google Search**: Check this box to allow Gemini to search the web for answers (e.g., current news, weather). * *Note: This checkbox is hidden while a conversation is active. Stop the conversation to change it.* + * **Use session memory**: Keep temporary memory for the current conversation session only. + * **Clear memory now**: Clear temporary memory before starting (or after stopping) a conversation. * **Microphone Toggle**: Mute/Unmute your microphone. * **Volume**: Adjust the AI's playback volume.