truthound-dashboard 1.0.1__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- truthound_dashboard/__init__.py +8 -1
- truthound_dashboard/cli.py +397 -0
- truthound_dashboard/translate/__init__.py +61 -0
- truthound_dashboard/translate/config_updater.py +327 -0
- truthound_dashboard/translate/exceptions.py +98 -0
- truthound_dashboard/translate/providers/__init__.py +49 -0
- truthound_dashboard/translate/providers/anthropic.py +135 -0
- truthound_dashboard/translate/providers/base.py +225 -0
- truthound_dashboard/translate/providers/mistral.py +138 -0
- truthound_dashboard/translate/providers/ollama.py +226 -0
- truthound_dashboard/translate/providers/openai.py +187 -0
- truthound_dashboard/translate/providers/registry.py +217 -0
- truthound_dashboard/translate/translator.py +443 -0
- {truthound_dashboard-1.0.1.dist-info → truthound_dashboard-1.1.0.dist-info}/METADATA +103 -4
- {truthound_dashboard-1.0.1.dist-info → truthound_dashboard-1.1.0.dist-info}/RECORD +18 -7
- {truthound_dashboard-1.0.1.dist-info → truthound_dashboard-1.1.0.dist-info}/WHEEL +0 -0
- {truthound_dashboard-1.0.1.dist-info → truthound_dashboard-1.1.0.dist-info}/entry_points.txt +0 -0
- {truthound_dashboard-1.0.1.dist-info → truthound_dashboard-1.1.0.dist-info}/licenses/LICENSE +0 -0
truthound_dashboard/__init__.py
CHANGED
|
@@ -7,5 +7,12 @@ A GX Cloud alternative that provides:
|
|
|
7
7
|
- Real-time monitoring dashboard
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
__version__ = version("truthound-dashboard")
|
|
14
|
+
except PackageNotFoundError:
|
|
15
|
+
# Package not installed (e.g., running from source without pip install -e)
|
|
16
|
+
__version__ = "0.0.0.dev"
|
|
17
|
+
|
|
11
18
|
__all__ = ["__version__"]
|
truthound_dashboard/cli.py
CHANGED
|
@@ -10,10 +10,14 @@ Example:
|
|
|
10
10
|
|
|
11
11
|
# Via truthound CLI plugin
|
|
12
12
|
truthound serve --port 8765
|
|
13
|
+
|
|
14
|
+
# Translate UI to additional languages
|
|
15
|
+
truthound translate -l ja,zh,de -p openai
|
|
13
16
|
"""
|
|
14
17
|
|
|
15
18
|
from __future__ import annotations
|
|
16
19
|
|
|
20
|
+
import asyncio
|
|
17
21
|
import webbrowser
|
|
18
22
|
from pathlib import Path
|
|
19
23
|
from typing import Annotated
|
|
@@ -21,6 +25,8 @@ from typing import Annotated
|
|
|
21
25
|
import typer
|
|
22
26
|
from rich.console import Console
|
|
23
27
|
from rich.panel import Panel
|
|
28
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
29
|
+
from rich.table import Table
|
|
24
30
|
|
|
25
31
|
from truthound_dashboard import __version__
|
|
26
32
|
|
|
@@ -179,6 +185,355 @@ def info() -> None:
|
|
|
179
185
|
)
|
|
180
186
|
|
|
181
187
|
|
|
188
|
+
@app.command()
|
|
189
|
+
def translate(
|
|
190
|
+
languages: Annotated[
|
|
191
|
+
str | None,
|
|
192
|
+
typer.Option(
|
|
193
|
+
"--languages",
|
|
194
|
+
"-l",
|
|
195
|
+
help="Target languages (comma-separated, e.g., ja,zh,de)",
|
|
196
|
+
),
|
|
197
|
+
] = None,
|
|
198
|
+
provider: Annotated[
|
|
199
|
+
str | None,
|
|
200
|
+
typer.Option(
|
|
201
|
+
"--provider",
|
|
202
|
+
"-p",
|
|
203
|
+
help="AI provider (openai, anthropic, ollama, mistral). Auto-detected if not specified.",
|
|
204
|
+
),
|
|
205
|
+
] = None,
|
|
206
|
+
model: Annotated[
|
|
207
|
+
str | None,
|
|
208
|
+
typer.Option(
|
|
209
|
+
"--model",
|
|
210
|
+
"-m",
|
|
211
|
+
help="Model name (e.g., gpt-4o, claude-sonnet-4-20250514). Uses provider default if not specified.",
|
|
212
|
+
),
|
|
213
|
+
] = None,
|
|
214
|
+
frontend_dir: Annotated[
|
|
215
|
+
Path | None,
|
|
216
|
+
typer.Option(
|
|
217
|
+
"--frontend-dir",
|
|
218
|
+
"-f",
|
|
219
|
+
help="Path to frontend directory. Auto-detected if not specified.",
|
|
220
|
+
exists=True,
|
|
221
|
+
file_okay=False,
|
|
222
|
+
resolve_path=True,
|
|
223
|
+
),
|
|
224
|
+
] = None,
|
|
225
|
+
dry_run: Annotated[
|
|
226
|
+
bool,
|
|
227
|
+
typer.Option(
|
|
228
|
+
"--dry-run",
|
|
229
|
+
help="Show what would be translated without making changes",
|
|
230
|
+
),
|
|
231
|
+
] = False,
|
|
232
|
+
list_providers: Annotated[
|
|
233
|
+
bool,
|
|
234
|
+
typer.Option(
|
|
235
|
+
"--list-providers",
|
|
236
|
+
help="List available AI providers and exit",
|
|
237
|
+
),
|
|
238
|
+
] = False,
|
|
239
|
+
list_languages: Annotated[
|
|
240
|
+
bool,
|
|
241
|
+
typer.Option(
|
|
242
|
+
"--list-languages",
|
|
243
|
+
help="List supported languages and exit",
|
|
244
|
+
),
|
|
245
|
+
] = False,
|
|
246
|
+
) -> None:
|
|
247
|
+
"""Translate UI to additional languages using AI.
|
|
248
|
+
|
|
249
|
+
This command uses AI providers to translate Intlayer content files
|
|
250
|
+
to new languages. Supports OpenAI, Anthropic, Ollama (local), and Mistral.
|
|
251
|
+
|
|
252
|
+
Examples:
|
|
253
|
+
# Translate to Japanese, Chinese, and German using OpenAI
|
|
254
|
+
truthound translate -l ja,zh,de -p openai
|
|
255
|
+
|
|
256
|
+
# Auto-detect provider based on environment variables
|
|
257
|
+
truthound translate -l ja,zh
|
|
258
|
+
|
|
259
|
+
# Use local Ollama (no API key needed)
|
|
260
|
+
truthound translate -l ja -p ollama
|
|
261
|
+
|
|
262
|
+
# Dry run to see what would be translated
|
|
263
|
+
truthound translate -l ja --dry-run
|
|
264
|
+
|
|
265
|
+
# List available providers
|
|
266
|
+
truthound translate --list-providers
|
|
267
|
+
|
|
268
|
+
# List supported languages
|
|
269
|
+
truthound translate --list-languages
|
|
270
|
+
"""
|
|
271
|
+
# Handle list options first
|
|
272
|
+
if list_providers:
|
|
273
|
+
_show_providers()
|
|
274
|
+
raise typer.Exit()
|
|
275
|
+
|
|
276
|
+
if list_languages:
|
|
277
|
+
_show_languages()
|
|
278
|
+
raise typer.Exit()
|
|
279
|
+
|
|
280
|
+
# Require languages for actual translation
|
|
281
|
+
if not languages:
|
|
282
|
+
console.print("[red]Error:[/red] --languages / -l is required for translation")
|
|
283
|
+
console.print("Use --list-languages to see supported languages")
|
|
284
|
+
raise typer.Exit(1)
|
|
285
|
+
|
|
286
|
+
# Parse languages
|
|
287
|
+
target_langs = [lang.strip().lower() for lang in languages.split(",")]
|
|
288
|
+
if not target_langs:
|
|
289
|
+
console.print("[red]Error:[/red] No languages specified")
|
|
290
|
+
raise typer.Exit(1)
|
|
291
|
+
|
|
292
|
+
# Find frontend directory
|
|
293
|
+
if frontend_dir is None:
|
|
294
|
+
frontend_dir = _find_frontend_dir()
|
|
295
|
+
if frontend_dir is None:
|
|
296
|
+
console.print(
|
|
297
|
+
"[red]Error:[/red] Could not find frontend directory. "
|
|
298
|
+
"Please specify with --frontend-dir"
|
|
299
|
+
)
|
|
300
|
+
raise typer.Exit(1)
|
|
301
|
+
|
|
302
|
+
# Run translation
|
|
303
|
+
asyncio.run(
|
|
304
|
+
_run_translation(
|
|
305
|
+
target_langs=target_langs,
|
|
306
|
+
provider_name=provider,
|
|
307
|
+
model_name=model,
|
|
308
|
+
frontend_dir=frontend_dir,
|
|
309
|
+
dry_run=dry_run,
|
|
310
|
+
)
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _show_providers() -> None:
|
|
315
|
+
"""Display available AI providers."""
|
|
316
|
+
try:
|
|
317
|
+
from truthound_dashboard.translate import list_available_providers
|
|
318
|
+
except ImportError:
|
|
319
|
+
console.print(
|
|
320
|
+
"[yellow]Warning:[/yellow] Translation module not available.\n"
|
|
321
|
+
"Install with: pip install truthound-dashboard[translate]"
|
|
322
|
+
)
|
|
323
|
+
raise typer.Exit(1)
|
|
324
|
+
|
|
325
|
+
providers = list_available_providers()
|
|
326
|
+
|
|
327
|
+
table = Table(title="Available AI Providers")
|
|
328
|
+
table.add_column("Provider", style="cyan")
|
|
329
|
+
table.add_column("Environment Variable", style="yellow")
|
|
330
|
+
table.add_column("Default Model", style="green")
|
|
331
|
+
table.add_column("Status", style="bold")
|
|
332
|
+
|
|
333
|
+
for p in providers:
|
|
334
|
+
status = "[green]Ready[/green]" if p["available"] else "[red]Not configured[/red]"
|
|
335
|
+
table.add_row(
|
|
336
|
+
p["display_name"],
|
|
337
|
+
p["env_var"],
|
|
338
|
+
p["default_model"],
|
|
339
|
+
status,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
console.print(table)
|
|
343
|
+
console.print("\n[dim]Set the environment variable to enable a provider.[/dim]")
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def _show_languages() -> None:
|
|
347
|
+
"""Display supported languages."""
|
|
348
|
+
try:
|
|
349
|
+
from truthound_dashboard.translate.config_updater import get_supported_languages
|
|
350
|
+
except ImportError:
|
|
351
|
+
console.print(
|
|
352
|
+
"[yellow]Warning:[/yellow] Translation module not available.\n"
|
|
353
|
+
"Install with: pip install truthound-dashboard[translate]"
|
|
354
|
+
)
|
|
355
|
+
raise typer.Exit(1)
|
|
356
|
+
|
|
357
|
+
languages = get_supported_languages()
|
|
358
|
+
|
|
359
|
+
table = Table(title="Supported Languages")
|
|
360
|
+
table.add_column("Code", style="cyan")
|
|
361
|
+
table.add_column("Name", style="green")
|
|
362
|
+
table.add_column("Native Name", style="yellow")
|
|
363
|
+
table.add_column("Flag")
|
|
364
|
+
|
|
365
|
+
for lang in sorted(languages, key=lambda x: x["code"]):
|
|
366
|
+
table.add_row(
|
|
367
|
+
lang["code"],
|
|
368
|
+
lang["name"],
|
|
369
|
+
lang["native_name"],
|
|
370
|
+
lang["flag"],
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
console.print(table)
|
|
374
|
+
console.print("\n[dim]Use comma-separated codes: -l ja,zh,de[/dim]")
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def _find_frontend_dir() -> Path | None:
|
|
378
|
+
"""Find the frontend directory relative to the package."""
|
|
379
|
+
import truthound_dashboard
|
|
380
|
+
|
|
381
|
+
# Try to find frontend relative to package
|
|
382
|
+
package_dir = Path(truthound_dashboard.__file__).parent
|
|
383
|
+
candidates = [
|
|
384
|
+
package_dir.parent.parent / "frontend", # Development layout
|
|
385
|
+
package_dir / "frontend", # Installed layout
|
|
386
|
+
Path.cwd() / "frontend", # Current directory
|
|
387
|
+
]
|
|
388
|
+
|
|
389
|
+
for candidate in candidates:
|
|
390
|
+
if candidate.exists() and (candidate / "src").exists():
|
|
391
|
+
return candidate
|
|
392
|
+
|
|
393
|
+
return None
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
async def _run_translation(
|
|
397
|
+
target_langs: list[str],
|
|
398
|
+
provider_name: str | None,
|
|
399
|
+
model_name: str | None,
|
|
400
|
+
frontend_dir: Path,
|
|
401
|
+
dry_run: bool,
|
|
402
|
+
) -> None:
|
|
403
|
+
"""Run the translation process."""
|
|
404
|
+
try:
|
|
405
|
+
from truthound_dashboard.translate import (
|
|
406
|
+
ContentTranslator,
|
|
407
|
+
IntlayerConfigUpdater,
|
|
408
|
+
ProviderConfig,
|
|
409
|
+
detect_provider,
|
|
410
|
+
get_provider,
|
|
411
|
+
)
|
|
412
|
+
from truthound_dashboard.translate.config_updater import LOCALE_MAPPINGS
|
|
413
|
+
from truthound_dashboard.translate.exceptions import (
|
|
414
|
+
APIKeyNotFoundError,
|
|
415
|
+
ProviderNotFoundError,
|
|
416
|
+
TranslationError,
|
|
417
|
+
)
|
|
418
|
+
except ImportError as e:
|
|
419
|
+
console.print(
|
|
420
|
+
f"[red]Error:[/red] Translation module not available: {e}\n"
|
|
421
|
+
"Install with: pip install truthound-dashboard[translate]"
|
|
422
|
+
)
|
|
423
|
+
raise typer.Exit(1)
|
|
424
|
+
|
|
425
|
+
# Validate languages
|
|
426
|
+
invalid_langs = [lang for lang in target_langs if lang not in LOCALE_MAPPINGS]
|
|
427
|
+
if invalid_langs:
|
|
428
|
+
console.print(
|
|
429
|
+
f"[red]Error:[/red] Unsupported language(s): {', '.join(invalid_langs)}\n"
|
|
430
|
+
"Use --list-languages to see supported languages."
|
|
431
|
+
)
|
|
432
|
+
raise typer.Exit(1)
|
|
433
|
+
|
|
434
|
+
# Get provider
|
|
435
|
+
try:
|
|
436
|
+
config = ProviderConfig(model=model_name) if model_name else None
|
|
437
|
+
|
|
438
|
+
if provider_name:
|
|
439
|
+
provider = get_provider(provider_name, config)
|
|
440
|
+
console.print(f"[green]✓[/green] Using provider: {provider_name}")
|
|
441
|
+
else:
|
|
442
|
+
provider = detect_provider(config)
|
|
443
|
+
console.print(
|
|
444
|
+
f"[green]✓[/green] Auto-detected provider: {provider.name}"
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
console.print(f"[green]✓[/green] Model: {provider.model}")
|
|
448
|
+
|
|
449
|
+
except ProviderNotFoundError as e:
|
|
450
|
+
console.print(f"[red]Error:[/red] {e}")
|
|
451
|
+
console.print("\nUse --list-providers to see available providers.")
|
|
452
|
+
raise typer.Exit(1)
|
|
453
|
+
except APIKeyNotFoundError as e:
|
|
454
|
+
console.print(f"[red]Error:[/red] {e}")
|
|
455
|
+
raise typer.Exit(1)
|
|
456
|
+
|
|
457
|
+
# Show what will be translated
|
|
458
|
+
console.print(f"[green]✓[/green] Frontend directory: {frontend_dir}")
|
|
459
|
+
console.print(f"[green]✓[/green] Target languages: {', '.join(target_langs)}")
|
|
460
|
+
|
|
461
|
+
if dry_run:
|
|
462
|
+
console.print("\n[yellow]Dry run mode - no changes will be made[/yellow]")
|
|
463
|
+
translator = ContentTranslator(provider, frontend_dir)
|
|
464
|
+
content_files = translator.find_content_files()
|
|
465
|
+
console.print(f"\nFound {len(content_files)} content files to translate:")
|
|
466
|
+
for f in content_files:
|
|
467
|
+
console.print(f" - {f.relative_to(frontend_dir)}")
|
|
468
|
+
raise typer.Exit()
|
|
469
|
+
|
|
470
|
+
# Run translation
|
|
471
|
+
console.print("\n[bold]Starting translation...[/bold]\n")
|
|
472
|
+
|
|
473
|
+
translator = ContentTranslator(provider, frontend_dir)
|
|
474
|
+
content_files = translator.find_content_files()
|
|
475
|
+
|
|
476
|
+
with Progress(
|
|
477
|
+
SpinnerColumn(),
|
|
478
|
+
TextColumn("[progress.description]{task.description}"),
|
|
479
|
+
console=console,
|
|
480
|
+
) as progress:
|
|
481
|
+
task = progress.add_task("Translating...", total=len(content_files))
|
|
482
|
+
|
|
483
|
+
def on_progress(current: int, total: int, filename: str) -> None:
|
|
484
|
+
progress.update(task, completed=current, description=f"Translating {filename}")
|
|
485
|
+
|
|
486
|
+
try:
|
|
487
|
+
results = await translator.translate_all(
|
|
488
|
+
target_langs=target_langs,
|
|
489
|
+
on_progress=on_progress,
|
|
490
|
+
)
|
|
491
|
+
except TranslationError as e:
|
|
492
|
+
console.print(f"\n[red]Translation failed:[/red] {e}")
|
|
493
|
+
raise typer.Exit(1)
|
|
494
|
+
|
|
495
|
+
# Update config files
|
|
496
|
+
console.print("\n[bold]Updating configuration...[/bold]")
|
|
497
|
+
try:
|
|
498
|
+
config_updater = IntlayerConfigUpdater(frontend_dir)
|
|
499
|
+
added_langs = config_updater.add_languages(target_langs)
|
|
500
|
+
if added_langs:
|
|
501
|
+
console.print(
|
|
502
|
+
f"[green]✓[/green] Added languages to config: {', '.join(added_langs)}"
|
|
503
|
+
)
|
|
504
|
+
else:
|
|
505
|
+
console.print("[dim]Languages already in config[/dim]")
|
|
506
|
+
except Exception as e:
|
|
507
|
+
console.print(f"[yellow]Warning:[/yellow] Could not update config: {e}")
|
|
508
|
+
|
|
509
|
+
# Show results
|
|
510
|
+
stats = translator.get_translation_stats(results)
|
|
511
|
+
|
|
512
|
+
console.print(
|
|
513
|
+
Panel(
|
|
514
|
+
f"[bold]Translation Complete[/bold]\n\n"
|
|
515
|
+
f"Files processed: {stats['files_processed']}\n"
|
|
516
|
+
f"Entries translated: {stats['entries_translated']}\n"
|
|
517
|
+
f"Entries skipped: {stats['entries_skipped']}\n"
|
|
518
|
+
f"Errors: {stats['total_errors']}",
|
|
519
|
+
title="Results",
|
|
520
|
+
border_style="green" if stats["total_errors"] == 0 else "yellow",
|
|
521
|
+
)
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
if stats["all_errors"]:
|
|
525
|
+
console.print("\n[yellow]Errors encountered:[/yellow]")
|
|
526
|
+
for error in stats["all_errors"][:10]: # Show first 10 errors
|
|
527
|
+
console.print(f" [red]•[/red] {error}")
|
|
528
|
+
if len(stats["all_errors"]) > 10:
|
|
529
|
+
console.print(f" ... and {len(stats['all_errors']) - 10} more errors")
|
|
530
|
+
|
|
531
|
+
console.print("\n[bold]Next steps:[/bold]")
|
|
532
|
+
console.print(" 1. Review the translated content files")
|
|
533
|
+
console.print(" 2. Rebuild the frontend: cd frontend && npm run build")
|
|
534
|
+
console.print(" 3. Start the server: truthound serve")
|
|
535
|
+
|
|
536
|
+
|
|
182
537
|
def register_commands(typer_app: typer.Typer) -> None:
|
|
183
538
|
"""Register commands with truthound CLI plugin system.
|
|
184
539
|
|
|
@@ -221,6 +576,48 @@ def register_commands(typer_app: typer.Typer) -> None:
|
|
|
221
576
|
reload=reload,
|
|
222
577
|
)
|
|
223
578
|
|
|
579
|
+
@typer_app.command(name="translate")
|
|
580
|
+
def translate_ui(
|
|
581
|
+
languages: Annotated[
|
|
582
|
+
str | None,
|
|
583
|
+
typer.Option("--languages", "-l", help="Target languages (comma-separated)"),
|
|
584
|
+
] = None,
|
|
585
|
+
provider: Annotated[
|
|
586
|
+
str | None,
|
|
587
|
+
typer.Option("--provider", "-p", help="AI provider"),
|
|
588
|
+
] = None,
|
|
589
|
+
model: Annotated[
|
|
590
|
+
str | None,
|
|
591
|
+
typer.Option("--model", "-m", help="Model name"),
|
|
592
|
+
] = None,
|
|
593
|
+
frontend_dir: Annotated[
|
|
594
|
+
Path | None,
|
|
595
|
+
typer.Option("--frontend-dir", "-f", help="Frontend directory path"),
|
|
596
|
+
] = None,
|
|
597
|
+
dry_run: Annotated[
|
|
598
|
+
bool,
|
|
599
|
+
typer.Option("--dry-run", help="Show what would be translated"),
|
|
600
|
+
] = False,
|
|
601
|
+
list_providers: Annotated[
|
|
602
|
+
bool,
|
|
603
|
+
typer.Option("--list-providers", help="List available AI providers"),
|
|
604
|
+
] = False,
|
|
605
|
+
list_languages: Annotated[
|
|
606
|
+
bool,
|
|
607
|
+
typer.Option("--list-languages", help="List supported languages"),
|
|
608
|
+
] = False,
|
|
609
|
+
) -> None:
|
|
610
|
+
"""Translate UI to additional languages using AI."""
|
|
611
|
+
translate(
|
|
612
|
+
languages=languages,
|
|
613
|
+
provider=provider,
|
|
614
|
+
model=model,
|
|
615
|
+
frontend_dir=frontend_dir,
|
|
616
|
+
dry_run=dry_run,
|
|
617
|
+
list_providers=list_providers,
|
|
618
|
+
list_languages=list_languages,
|
|
619
|
+
)
|
|
620
|
+
|
|
224
621
|
|
|
225
622
|
if __name__ == "__main__":
|
|
226
623
|
app()
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Translation module for truthound-dashboard.
|
|
2
|
+
|
|
3
|
+
This module provides AI-powered translation capabilities for Intlayer content files.
|
|
4
|
+
It supports multiple AI providers and can automatically detect available providers
|
|
5
|
+
based on environment variables.
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
# CLI usage
|
|
9
|
+
truthound translate -l ja,zh,de -p openai
|
|
10
|
+
|
|
11
|
+
# Auto-detect provider
|
|
12
|
+
truthound translate -l ja,zh
|
|
13
|
+
|
|
14
|
+
Supported Providers:
|
|
15
|
+
- OpenAI (GPT-4, GPT-3.5)
|
|
16
|
+
- Anthropic (Claude 3)
|
|
17
|
+
- Ollama (local LLM, no API key required)
|
|
18
|
+
- Mistral
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from truthound_dashboard.translate.providers import (
|
|
22
|
+
AIProvider,
|
|
23
|
+
ProviderConfig,
|
|
24
|
+
ProviderRegistry,
|
|
25
|
+
get_provider,
|
|
26
|
+
detect_provider,
|
|
27
|
+
list_available_providers,
|
|
28
|
+
)
|
|
29
|
+
from truthound_dashboard.translate.translator import (
|
|
30
|
+
ContentTranslator,
|
|
31
|
+
TranslationResult,
|
|
32
|
+
)
|
|
33
|
+
from truthound_dashboard.translate.config_updater import (
|
|
34
|
+
IntlayerConfigUpdater,
|
|
35
|
+
)
|
|
36
|
+
from truthound_dashboard.translate.exceptions import (
|
|
37
|
+
TranslationError,
|
|
38
|
+
ProviderNotFoundError,
|
|
39
|
+
APIKeyNotFoundError,
|
|
40
|
+
TranslationAPIError,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
# Providers
|
|
45
|
+
"AIProvider",
|
|
46
|
+
"ProviderConfig",
|
|
47
|
+
"ProviderRegistry",
|
|
48
|
+
"get_provider",
|
|
49
|
+
"detect_provider",
|
|
50
|
+
"list_available_providers",
|
|
51
|
+
# Translator
|
|
52
|
+
"ContentTranslator",
|
|
53
|
+
"TranslationResult",
|
|
54
|
+
# Config
|
|
55
|
+
"IntlayerConfigUpdater",
|
|
56
|
+
# Exceptions
|
|
57
|
+
"TranslationError",
|
|
58
|
+
"ProviderNotFoundError",
|
|
59
|
+
"APIKeyNotFoundError",
|
|
60
|
+
"TranslationAPIError",
|
|
61
|
+
]
|