agentvibes 5.7.6 → 5.9.0

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.
Files changed (137) hide show
  1. package/.agentvibes/config.json +12 -5
  2. package/.agentvibes/install-manifest.json +188 -300
  3. package/.claude/audio/tracks/celestial_velvet.mp3 +0 -0
  4. package/.claude/commands/agent-vibes-bmad-voices.md +117 -117
  5. package/.claude/commands/agent-vibes-rdp.md +24 -24
  6. package/.claude/config/audio-effects.cfg +3 -2
  7. package/.claude/config/audio-effects.cfg.sample +52 -52
  8. package/.claude/config/background-music-enabled.txt +1 -0
  9. package/.claude/config/background-music-position.txt +1 -1
  10. package/.claude/config/language.txt +1 -0
  11. package/.claude/docs/TERMUX_SETUP.md +408 -408
  12. package/.claude/hooks/audio-cache-utils.sh +0 -0
  13. package/.claude/hooks/audio-processor.sh +0 -0
  14. package/.claude/hooks/background-music-manager.sh +0 -0
  15. package/.claude/hooks/bmad-party-speak.sh +27 -6
  16. package/.claude/hooks/bmad-speak-enhanced.sh +0 -0
  17. package/.claude/hooks/bmad-speak.sh +0 -0
  18. package/.claude/hooks/bmad-tts-injector.sh +0 -0
  19. package/.claude/hooks/bmad-voice-manager.sh +0 -0
  20. package/.claude/hooks/clawdbot-receiver-SECURE.sh +0 -0
  21. package/.claude/hooks/clawdbot-receiver.sh +0 -0
  22. package/.claude/hooks/clean-audio-cache.sh +0 -0
  23. package/.claude/hooks/cleanup-cache.sh +0 -0
  24. package/.claude/hooks/configure-rdp-mode.sh +0 -0
  25. package/.claude/hooks/download-extra-voices.sh +0 -0
  26. package/.claude/hooks/effects-manager.sh +0 -0
  27. package/.claude/hooks/github-star-reminder.sh +0 -0
  28. package/.claude/hooks/language-manager.sh +0 -0
  29. package/.claude/hooks/learn-manager.sh +0 -0
  30. package/.claude/hooks/macos-voice-manager.sh +0 -0
  31. package/.claude/hooks/migrate-background-music.sh +0 -0
  32. package/.claude/hooks/migrate-to-agentvibes.sh +0 -0
  33. package/.claude/hooks/optimize-background-music.sh +0 -0
  34. package/.claude/hooks/path-resolver.sh +0 -0
  35. package/.claude/hooks/personality-manager.sh +0 -0
  36. package/.claude/hooks/piper-download-voices.sh +0 -0
  37. package/.claude/hooks/piper-installer.sh +0 -0
  38. package/.claude/hooks/piper-multispeaker-registry.sh +0 -0
  39. package/.claude/hooks/piper-voice-manager.sh +0 -0
  40. package/.claude/hooks/play-tts-agentvibes-receiver-for-voiceless-connections.sh +0 -0
  41. package/.claude/hooks/play-tts-agentvibes-receiver.sh +1 -0
  42. package/.claude/hooks/play-tts-enhanced.sh +0 -0
  43. package/.claude/hooks/play-tts-macos.sh +0 -0
  44. package/.claude/hooks/play-tts-piper.sh +0 -0
  45. package/.claude/hooks/play-tts-soprano.sh +0 -0
  46. package/.claude/hooks/play-tts-ssh-remote.sh +11 -8
  47. package/.claude/hooks/play-tts-termux-ssh.sh +0 -0
  48. package/.claude/hooks/play-tts-windows-receiver.sh +0 -0
  49. package/.claude/hooks/play-tts.sh +0 -0
  50. package/.claude/hooks/prepare-release.sh +0 -0
  51. package/.claude/hooks/provider-commands.sh +0 -0
  52. package/.claude/hooks/provider-manager.sh +0 -0
  53. package/.claude/hooks/replay-target-audio.sh +0 -0
  54. package/.claude/hooks/requirements.txt +6 -6
  55. package/.claude/hooks/sentiment-manager.sh +0 -0
  56. package/.claude/hooks/session-start-tts.sh +0 -0
  57. package/.claude/hooks/soprano-gradio-synth.py +139 -139
  58. package/.claude/hooks/speed-manager.sh +0 -0
  59. package/.claude/hooks/stop-tts.sh +0 -0
  60. package/.claude/hooks/termux-installer.sh +0 -0
  61. package/.claude/hooks/translate-manager.sh +0 -0
  62. package/.claude/hooks/translator.py +237 -237
  63. package/.claude/hooks/tts-queue-worker.sh +0 -0
  64. package/.claude/hooks/tts-queue.sh +0 -0
  65. package/.claude/hooks/verbosity-manager.sh +0 -0
  66. package/.claude/hooks/voice-manager.sh +0 -0
  67. package/.claude/hooks-windows/audio-cache-utils.ps1 +119 -119
  68. package/.claude/hooks-windows/audio-cache-utils.ps1.user.bak +119 -0
  69. package/.claude/hooks-windows/bmad-speak.ps1 +9 -38
  70. package/.claude/hooks-windows/play-tts-soprano.ps1 +13 -2
  71. package/.claude/hooks-windows/soprano-gradio-synth.py +153 -153
  72. package/.claude/hooks-windows/soprano-gradio-synth.py.user.bak +153 -0
  73. package/.claude/piper-voices-dir.txt +1 -1
  74. package/.claude/verbosity.txt +1 -1
  75. package/.clawdbot/README.md +105 -105
  76. package/.mcp.json +5 -14
  77. package/README.md +43 -2
  78. package/RELEASE_NOTES.md +110 -0
  79. package/WINDOWS-SETUP.md +208 -208
  80. package/bin/agent-vibes +39 -39
  81. package/bin/agentvibes-voice-browser.js +0 -0
  82. package/bin/agentvibes.js +0 -0
  83. package/bin/mcp-server.js +121 -121
  84. package/bin/mcp-server.sh +0 -0
  85. package/bin/test-bmad-pr +78 -78
  86. package/mcp-server/QUICK_START.md +203 -203
  87. package/mcp-server/README.md +345 -345
  88. package/mcp-server/WINDOWS_SETUP.md +0 -0
  89. package/mcp-server/examples/claude_desktop_config.json +11 -11
  90. package/mcp-server/examples/claude_desktop_config_piper.json +9 -9
  91. package/mcp-server/examples/custom_instructions.md +169 -169
  92. package/mcp-server/install-deps.js +0 -0
  93. package/mcp-server/server.py +1797 -1797
  94. package/mcp-server/test_server.py +0 -0
  95. package/package.json +1 -1
  96. package/src/cli/list-personalities.js +110 -110
  97. package/src/cli/list-voices.js +114 -114
  98. package/src/commands/bmad-voices.js +394 -394
  99. package/src/commands/install-mcp.js +476 -476
  100. package/src/console/audio-env.js +4 -1
  101. package/src/console/brand-colors.js +13 -13
  102. package/src/console/constants/personalities.js +44 -44
  103. package/src/console/tabs/agents-tab.js +85 -62
  104. package/src/console/tabs/help-tab.js +314 -314
  105. package/src/console/tabs/music-tab.js +3 -0
  106. package/src/console/tabs/readme-tab.js +272 -272
  107. package/src/console/tabs/setup-tab.js +285 -41
  108. package/src/console/tabs/voices-tab.js +14 -2
  109. package/src/console/widgets/destroy-list.js +25 -25
  110. package/src/console/widgets/notice.js +55 -55
  111. package/src/i18n/de.js +202 -202
  112. package/src/i18n/es.js +202 -202
  113. package/src/i18n/fr.js +202 -202
  114. package/src/i18n/hi.js +202 -202
  115. package/src/i18n/ja.js +202 -202
  116. package/src/i18n/ko.js +202 -202
  117. package/src/i18n/pt.js +202 -202
  118. package/src/i18n/strings.js +54 -54
  119. package/src/i18n/zh-CN.js +202 -202
  120. package/src/installer/language-screen.js +31 -31
  121. package/src/installer/music-file-input.js +304 -304
  122. package/src/installer.js +0 -0
  123. package/src/services/config-service.js +264 -264
  124. package/src/services/language-service.js +47 -47
  125. package/src/services/provider-service.js +143 -143
  126. package/src/utils/audio-duration-validator.js +298 -298
  127. package/src/utils/audio-format-validator.js +277 -277
  128. package/src/utils/dependency-checker.js +469 -469
  129. package/src/utils/file-ownership-verifier.js +358 -358
  130. package/src/utils/list-formatter.js +194 -194
  131. package/src/utils/music-file-validator.js +285 -285
  132. package/src/utils/preview-list-prompt.js +136 -136
  133. package/src/utils/secure-music-storage.js +412 -412
  134. package/templates/agentvibes-receiver.sh +231 -231
  135. package/templates/audio/welcome-music.mp3 +0 -0
  136. package/.claude/hooks/bmad-party-manager.sh +0 -225
  137. package/.claude/hooks/stop.sh +0 -38
@@ -1,237 +1,237 @@
1
- #!/usr/bin/env python3
2
- #
3
- # File: .claude/hooks/translator.py
4
- #
5
- # AgentVibes - Finally, your AI Agents can Talk Back! Text-to-Speech WITH personality for AI Assistants!
6
- # Website: https://agentvibes.org
7
- # Repository: https://github.com/paulpreibisch/AgentVibes
8
- #
9
- # Co-created by Paul Preibisch with Claude AI
10
- # Copyright (c) 2025 Paul Preibisch
11
- #
12
- # Licensed under the Apache License, Version 2.0 (the "License");
13
- # you may not use this file except in compliance with the License.
14
- # You may obtain a copy of the License at
15
- #
16
- # http://www.apache.org/licenses/LICENSE-2.0
17
- #
18
- # Unless required by applicable law or agreed to in writing, software
19
- # distributed under the License is distributed on an "AS IS" BASIS,
20
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
- # See the License for the specific language governing permissions and
22
- # limitations under the License.
23
- #
24
- # DISCLAIMER: This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
- # express or implied. Use at your own risk. See the Apache License for details.
26
- #
27
- # ---
28
- #
29
- # @fileoverview Text translator for multi-language TTS and learning mode
30
- # @context Provides automatic translation using Google Translate via deep-translator library
31
- # @architecture Standalone CLI module callable from bash scripts, with library mode for Python imports
32
- # @dependencies deep-translator, langdetect (pip install deep-translator langdetect)
33
- # @entrypoints CLI: python3 translator.py <text> <target_lang>, Library: from translator import translate
34
- # @patterns Command pattern - supports translate, detect, and batch operations
35
- # @related play-tts.sh, learn-manager.sh, language-manager.sh
36
- #
37
-
38
- """
39
- Text translation utilities for AgentVibes multi-language TTS.
40
-
41
- Provides automatic translation of TTS text to the user's preferred language,
42
- supporting both BMAD communication_language settings and learning mode.
43
-
44
- Usage:
45
- CLI: python3 translator.py <text> <target_language>
46
- Library: from translator import translate, detect_language
47
- """
48
-
49
- import sys
50
- import os
51
- from typing import Optional, Tuple
52
-
53
- # Language name to ISO code mapping
54
- LANG_CODES = {
55
- 'spanish': 'es', 'español': 'es', 'es': 'es',
56
- 'french': 'fr', 'français': 'fr', 'fr': 'fr',
57
- 'german': 'de', 'deutsch': 'de', 'de': 'de',
58
- 'italian': 'it', 'italiano': 'it', 'it': 'it',
59
- 'portuguese': 'pt', 'português': 'pt', 'pt': 'pt',
60
- 'chinese': 'zh-CN', 'mandarin': 'zh-CN', 'zh': 'zh-CN', '中文': 'zh-CN',
61
- 'japanese': 'ja', '日本語': 'ja', 'ja': 'ja',
62
- 'korean': 'ko', '한국어': 'ko', 'ko': 'ko',
63
- 'russian': 'ru', 'русский': 'ru', 'ru': 'ru',
64
- 'polish': 'pl', 'polski': 'pl', 'pl': 'pl',
65
- 'dutch': 'nl', 'nederlands': 'nl', 'nl': 'nl',
66
- 'turkish': 'tr', 'türkçe': 'tr', 'tr': 'tr',
67
- 'arabic': 'ar', 'العربية': 'ar', 'ar': 'ar',
68
- 'hindi': 'hi', 'हिन्दी': 'hi', 'hi': 'hi',
69
- 'swedish': 'sv', 'svenska': 'sv', 'sv': 'sv',
70
- 'danish': 'da', 'dansk': 'da', 'da': 'da',
71
- 'norwegian': 'no', 'norsk': 'no', 'no': 'no',
72
- 'finnish': 'fi', 'suomi': 'fi', 'fi': 'fi',
73
- 'czech': 'cs', 'čeština': 'cs', 'cs': 'cs',
74
- 'romanian': 'ro', 'română': 'ro', 'ro': 'ro',
75
- 'ukrainian': 'uk', 'українська': 'uk', 'uk': 'uk',
76
- 'greek': 'el', 'ελληνικά': 'el', 'el': 'el',
77
- 'bulgarian': 'bg', 'български': 'bg', 'bg': 'bg',
78
- 'croatian': 'hr', 'hrvatski': 'hr', 'hr': 'hr',
79
- 'slovak': 'sk', 'slovenčina': 'sk', 'sk': 'sk',
80
- 'english': 'en', 'en': 'en',
81
- }
82
-
83
-
84
- def get_lang_code(language: str) -> str:
85
- """
86
- Convert language name to ISO code.
87
-
88
- Args:
89
- language: Language name or code (e.g., 'spanish', 'es', 'español')
90
-
91
- Returns:
92
- ISO language code (e.g., 'es')
93
- """
94
- lang_lower = language.lower().strip()
95
- return LANG_CODES.get(lang_lower, lang_lower)
96
-
97
-
98
- def detect_language(text: str) -> Optional[str]:
99
- """
100
- Detect the language of given text.
101
-
102
- Args:
103
- text: Text to analyze
104
-
105
- Returns:
106
- Language code (e.g., 'es', 'fr', 'en') or None if detection fails
107
- """
108
- if not text or len(text.strip()) < 3:
109
- return None
110
-
111
- try:
112
- from langdetect import detect, LangDetectException
113
- return detect(text)
114
- except ImportError:
115
- print("Warning: langdetect not installed. Run: pip install langdetect", file=sys.stderr)
116
- return None
117
- except Exception:
118
- return None
119
-
120
-
121
- def translate(text: str, target_lang: str, source_lang: str = 'en') -> Tuple[str, bool]:
122
- """
123
- Translate text to target language.
124
-
125
- Args:
126
- text: Text to translate
127
- target_lang: Target language (name or code)
128
- source_lang: Source language (default: 'en')
129
-
130
- Returns:
131
- Tuple of (translated_text, success)
132
- """
133
- if not text or not text.strip():
134
- return text, False
135
-
136
- # Convert language names to codes
137
- target_code = get_lang_code(target_lang)
138
- source_code = get_lang_code(source_lang)
139
-
140
- # Skip if source and target are the same
141
- if target_code == source_code:
142
- return text, False
143
-
144
- # Skip if target is English and source is also English
145
- if target_code == 'en' and source_code == 'en':
146
- return text, False
147
-
148
- try:
149
- from deep_translator import GoogleTranslator
150
-
151
- translator = GoogleTranslator(source=source_code, target=target_code)
152
- translated = translator.translate(text)
153
-
154
- if translated:
155
- return translated, True
156
- return text, False
157
-
158
- except ImportError:
159
- print("Error: deep-translator not installed. Run: pip install deep-translator", file=sys.stderr)
160
- return text, False
161
- except Exception as e:
162
- print(f"Translation error: {e}", file=sys.stderr)
163
- return text, False
164
-
165
-
166
- def translate_auto(text: str, target_lang: str) -> Tuple[str, bool, Optional[str]]:
167
- """
168
- Translate text to target language with auto-detection of source language.
169
-
170
- Args:
171
- text: Text to translate
172
- target_lang: Target language (name or code)
173
-
174
- Returns:
175
- Tuple of (translated_text, success, detected_source_lang)
176
- """
177
- if not text or not text.strip():
178
- return text, False, None
179
-
180
- # Detect source language
181
- detected = detect_language(text)
182
-
183
- # Convert target to code
184
- target_code = get_lang_code(target_lang)
185
-
186
- # Skip if detected language matches target
187
- if detected and detected == target_code:
188
- return text, False, detected
189
-
190
- # Translate
191
- translated, success = translate(text, target_lang, source_lang=detected or 'en')
192
- return translated, success, detected
193
-
194
-
195
- def main():
196
- """CLI entry point for translator."""
197
- if len(sys.argv) < 3:
198
- print("Usage: translator.py <text> <target_language> [source_language]", file=sys.stderr)
199
- print(" translator.py detect <text>", file=sys.stderr)
200
- print("", file=sys.stderr)
201
- print("Examples:", file=sys.stderr)
202
- print(" translator.py 'Hello world' spanish", file=sys.stderr)
203
- print(" translator.py 'Hello world' es en", file=sys.stderr)
204
- print(" translator.py detect 'Hola mundo'", file=sys.stderr)
205
- sys.exit(1)
206
-
207
- command = sys.argv[1]
208
-
209
- # Detection mode
210
- if command == 'detect':
211
- if len(sys.argv) < 3:
212
- print("Usage: translator.py detect <text>", file=sys.stderr)
213
- sys.exit(1)
214
- text = sys.argv[2]
215
- detected = detect_language(text)
216
- if detected:
217
- print(detected)
218
- else:
219
- print("unknown")
220
- sys.exit(0)
221
-
222
- # Translation mode
223
- text = sys.argv[1]
224
- target_lang = sys.argv[2]
225
- source_lang = sys.argv[3] if len(sys.argv) > 3 else 'en'
226
-
227
- translated, success = translate(text, target_lang, source_lang)
228
-
229
- # Output the result (for shell script consumption)
230
- print(translated)
231
-
232
- # Exit with appropriate code
233
- sys.exit(0 if success else 1)
234
-
235
-
236
- if __name__ == '__main__':
237
- main()
1
+ #!/usr/bin/env python3
2
+ #
3
+ # File: .claude/hooks/translator.py
4
+ #
5
+ # AgentVibes - Finally, your AI Agents can Talk Back! Text-to-Speech WITH personality for AI Assistants!
6
+ # Website: https://agentvibes.org
7
+ # Repository: https://github.com/paulpreibisch/AgentVibes
8
+ #
9
+ # Co-created by Paul Preibisch with Claude AI
10
+ # Copyright (c) 2025 Paul Preibisch
11
+ #
12
+ # Licensed under the Apache License, Version 2.0 (the "License");
13
+ # you may not use this file except in compliance with the License.
14
+ # You may obtain a copy of the License at
15
+ #
16
+ # http://www.apache.org/licenses/LICENSE-2.0
17
+ #
18
+ # Unless required by applicable law or agreed to in writing, software
19
+ # distributed under the License is distributed on an "AS IS" BASIS,
20
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
+ # See the License for the specific language governing permissions and
22
+ # limitations under the License.
23
+ #
24
+ # DISCLAIMER: This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # express or implied. Use at your own risk. See the Apache License for details.
26
+ #
27
+ # ---
28
+ #
29
+ # @fileoverview Text translator for multi-language TTS and learning mode
30
+ # @context Provides automatic translation using Google Translate via deep-translator library
31
+ # @architecture Standalone CLI module callable from bash scripts, with library mode for Python imports
32
+ # @dependencies deep-translator, langdetect (pip install deep-translator langdetect)
33
+ # @entrypoints CLI: python3 translator.py <text> <target_lang>, Library: from translator import translate
34
+ # @patterns Command pattern - supports translate, detect, and batch operations
35
+ # @related play-tts.sh, learn-manager.sh, language-manager.sh
36
+ #
37
+
38
+ """
39
+ Text translation utilities for AgentVibes multi-language TTS.
40
+
41
+ Provides automatic translation of TTS text to the user's preferred language,
42
+ supporting both BMAD communication_language settings and learning mode.
43
+
44
+ Usage:
45
+ CLI: python3 translator.py <text> <target_language>
46
+ Library: from translator import translate, detect_language
47
+ """
48
+
49
+ import sys
50
+ import os
51
+ from typing import Optional, Tuple
52
+
53
+ # Language name to ISO code mapping
54
+ LANG_CODES = {
55
+ 'spanish': 'es', 'español': 'es', 'es': 'es',
56
+ 'french': 'fr', 'français': 'fr', 'fr': 'fr',
57
+ 'german': 'de', 'deutsch': 'de', 'de': 'de',
58
+ 'italian': 'it', 'italiano': 'it', 'it': 'it',
59
+ 'portuguese': 'pt', 'português': 'pt', 'pt': 'pt',
60
+ 'chinese': 'zh-CN', 'mandarin': 'zh-CN', 'zh': 'zh-CN', '中文': 'zh-CN',
61
+ 'japanese': 'ja', '日本語': 'ja', 'ja': 'ja',
62
+ 'korean': 'ko', '한국어': 'ko', 'ko': 'ko',
63
+ 'russian': 'ru', 'русский': 'ru', 'ru': 'ru',
64
+ 'polish': 'pl', 'polski': 'pl', 'pl': 'pl',
65
+ 'dutch': 'nl', 'nederlands': 'nl', 'nl': 'nl',
66
+ 'turkish': 'tr', 'türkçe': 'tr', 'tr': 'tr',
67
+ 'arabic': 'ar', 'العربية': 'ar', 'ar': 'ar',
68
+ 'hindi': 'hi', 'हिन्दी': 'hi', 'hi': 'hi',
69
+ 'swedish': 'sv', 'svenska': 'sv', 'sv': 'sv',
70
+ 'danish': 'da', 'dansk': 'da', 'da': 'da',
71
+ 'norwegian': 'no', 'norsk': 'no', 'no': 'no',
72
+ 'finnish': 'fi', 'suomi': 'fi', 'fi': 'fi',
73
+ 'czech': 'cs', 'čeština': 'cs', 'cs': 'cs',
74
+ 'romanian': 'ro', 'română': 'ro', 'ro': 'ro',
75
+ 'ukrainian': 'uk', 'українська': 'uk', 'uk': 'uk',
76
+ 'greek': 'el', 'ελληνικά': 'el', 'el': 'el',
77
+ 'bulgarian': 'bg', 'български': 'bg', 'bg': 'bg',
78
+ 'croatian': 'hr', 'hrvatski': 'hr', 'hr': 'hr',
79
+ 'slovak': 'sk', 'slovenčina': 'sk', 'sk': 'sk',
80
+ 'english': 'en', 'en': 'en',
81
+ }
82
+
83
+
84
+ def get_lang_code(language: str) -> str:
85
+ """
86
+ Convert language name to ISO code.
87
+
88
+ Args:
89
+ language: Language name or code (e.g., 'spanish', 'es', 'español')
90
+
91
+ Returns:
92
+ ISO language code (e.g., 'es')
93
+ """
94
+ lang_lower = language.lower().strip()
95
+ return LANG_CODES.get(lang_lower, lang_lower)
96
+
97
+
98
+ def detect_language(text: str) -> Optional[str]:
99
+ """
100
+ Detect the language of given text.
101
+
102
+ Args:
103
+ text: Text to analyze
104
+
105
+ Returns:
106
+ Language code (e.g., 'es', 'fr', 'en') or None if detection fails
107
+ """
108
+ if not text or len(text.strip()) < 3:
109
+ return None
110
+
111
+ try:
112
+ from langdetect import detect, LangDetectException
113
+ return detect(text)
114
+ except ImportError:
115
+ print("Warning: langdetect not installed. Run: pip install langdetect", file=sys.stderr)
116
+ return None
117
+ except Exception:
118
+ return None
119
+
120
+
121
+ def translate(text: str, target_lang: str, source_lang: str = 'en') -> Tuple[str, bool]:
122
+ """
123
+ Translate text to target language.
124
+
125
+ Args:
126
+ text: Text to translate
127
+ target_lang: Target language (name or code)
128
+ source_lang: Source language (default: 'en')
129
+
130
+ Returns:
131
+ Tuple of (translated_text, success)
132
+ """
133
+ if not text or not text.strip():
134
+ return text, False
135
+
136
+ # Convert language names to codes
137
+ target_code = get_lang_code(target_lang)
138
+ source_code = get_lang_code(source_lang)
139
+
140
+ # Skip if source and target are the same
141
+ if target_code == source_code:
142
+ return text, False
143
+
144
+ # Skip if target is English and source is also English
145
+ if target_code == 'en' and source_code == 'en':
146
+ return text, False
147
+
148
+ try:
149
+ from deep_translator import GoogleTranslator
150
+
151
+ translator = GoogleTranslator(source=source_code, target=target_code)
152
+ translated = translator.translate(text)
153
+
154
+ if translated:
155
+ return translated, True
156
+ return text, False
157
+
158
+ except ImportError:
159
+ print("Error: deep-translator not installed. Run: pip install deep-translator", file=sys.stderr)
160
+ return text, False
161
+ except Exception as e:
162
+ print(f"Translation error: {e}", file=sys.stderr)
163
+ return text, False
164
+
165
+
166
+ def translate_auto(text: str, target_lang: str) -> Tuple[str, bool, Optional[str]]:
167
+ """
168
+ Translate text to target language with auto-detection of source language.
169
+
170
+ Args:
171
+ text: Text to translate
172
+ target_lang: Target language (name or code)
173
+
174
+ Returns:
175
+ Tuple of (translated_text, success, detected_source_lang)
176
+ """
177
+ if not text or not text.strip():
178
+ return text, False, None
179
+
180
+ # Detect source language
181
+ detected = detect_language(text)
182
+
183
+ # Convert target to code
184
+ target_code = get_lang_code(target_lang)
185
+
186
+ # Skip if detected language matches target
187
+ if detected and detected == target_code:
188
+ return text, False, detected
189
+
190
+ # Translate
191
+ translated, success = translate(text, target_lang, source_lang=detected or 'en')
192
+ return translated, success, detected
193
+
194
+
195
+ def main():
196
+ """CLI entry point for translator."""
197
+ if len(sys.argv) < 3:
198
+ print("Usage: translator.py <text> <target_language> [source_language]", file=sys.stderr)
199
+ print(" translator.py detect <text>", file=sys.stderr)
200
+ print("", file=sys.stderr)
201
+ print("Examples:", file=sys.stderr)
202
+ print(" translator.py 'Hello world' spanish", file=sys.stderr)
203
+ print(" translator.py 'Hello world' es en", file=sys.stderr)
204
+ print(" translator.py detect 'Hola mundo'", file=sys.stderr)
205
+ sys.exit(1)
206
+
207
+ command = sys.argv[1]
208
+
209
+ # Detection mode
210
+ if command == 'detect':
211
+ if len(sys.argv) < 3:
212
+ print("Usage: translator.py detect <text>", file=sys.stderr)
213
+ sys.exit(1)
214
+ text = sys.argv[2]
215
+ detected = detect_language(text)
216
+ if detected:
217
+ print(detected)
218
+ else:
219
+ print("unknown")
220
+ sys.exit(0)
221
+
222
+ # Translation mode
223
+ text = sys.argv[1]
224
+ target_lang = sys.argv[2]
225
+ source_lang = sys.argv[3] if len(sys.argv) > 3 else 'en'
226
+
227
+ translated, success = translate(text, target_lang, source_lang)
228
+
229
+ # Output the result (for shell script consumption)
230
+ print(translated)
231
+
232
+ # Exit with appropriate code
233
+ sys.exit(0 if success else 1)
234
+
235
+
236
+ if __name__ == '__main__':
237
+ main()
File without changes
File without changes
File without changes
File without changes