@magmamath/students-features 1.3.23-rc.2 → 1.3.23-rc.21
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.
- package/dist/commonjs/features/translation/constants.js +11 -0
- package/dist/commonjs/features/translation/constants.js.map +1 -0
- package/dist/commonjs/features/translation/helpers.js +60 -0
- package/dist/commonjs/features/translation/helpers.js.map +1 -0
- package/dist/commonjs/features/translation/index.js +105 -0
- package/dist/commonjs/features/translation/index.js.map +1 -0
- package/dist/commonjs/features/translation/model/TranslationModel.js +122 -0
- package/dist/commonjs/features/translation/model/TranslationModel.js.map +1 -0
- package/dist/commonjs/features/translation/model/TranslationPreprocessor.js +142 -0
- package/dist/commonjs/features/translation/model/TranslationPreprocessor.js.map +1 -0
- package/dist/commonjs/features/translation/model/TranslationService.js +112 -0
- package/dist/commonjs/features/translation/model/TranslationService.js.map +1 -0
- package/dist/commonjs/features/translation/preserve/wordsToPreserve.js +314 -0
- package/dist/commonjs/features/translation/preserve/wordsToPreserve.js.map +1 -0
- package/dist/commonjs/features/translation/providers/google/GoogleTranslationProvider.js +50 -0
- package/dist/commonjs/features/translation/providers/google/GoogleTranslationProvider.js.map +1 -0
- package/dist/commonjs/features/translation/providers/google/supportedLanguages.js +230 -0
- package/dist/commonjs/features/translation/providers/google/supportedLanguages.js.map +1 -0
- package/dist/commonjs/features/translation/providers/google.types.js +2 -0
- package/dist/commonjs/features/translation/providers/google.types.js.map +1 -0
- package/dist/commonjs/features/translation/providers/translation.interface.js +49 -0
- package/dist/commonjs/features/translation/providers/translation.interface.js.map +1 -0
- package/dist/commonjs/features/translation/types.js +2 -0
- package/dist/commonjs/features/translation/types.js.map +1 -0
- package/dist/commonjs/features/voice/index.js +4 -4
- package/dist/commonjs/features/voice/index.js.map +1 -1
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptContent.js +44 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptContent.js.map +1 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscription.js +107 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscription.js.map +1 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionCollapsible.js +66 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionCollapsible.js.map +1 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionHeaderActions.js +58 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionHeaderActions.js.map +1 -0
- package/dist/commonjs/features/voice/playing/hooks/{useVoiceTranscriptionsDropdown.js → useDropdownAnimation.js} +8 -7
- package/dist/commonjs/features/voice/playing/hooks/useDropdownAnimation.js.map +1 -0
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionController.js +128 -0
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionController.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/{VoiceTranscriptionsDropdown.model.js → Dropdown.model.js} +4 -4
- package/dist/commonjs/features/voice/playing/model/Dropdown.model.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/PlaybackController.js +183 -0
- package/dist/commonjs/features/voice/playing/model/PlaybackController.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/Player.model.js +24 -1
- package/dist/commonjs/features/voice/playing/model/Player.model.js.map +1 -1
- package/dist/commonjs/features/voice/playing/model/{VoiceTranscriptionsCollection.js → TranscriptionsCollection.js} +4 -4
- package/dist/commonjs/features/voice/playing/model/TranscriptionsCollection.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/TranscriptionsDownloader.model.js +82 -0
- package/dist/commonjs/features/voice/playing/model/TranscriptionsDownloader.model.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/Translation.model.js +62 -0
- package/dist/commonjs/features/voice/playing/model/Translation.model.js.map +1 -0
- package/dist/commonjs/features/voice/playing/model/VoiceFileDownloader.model.js +2 -2
- package/dist/commonjs/features/voice/playing/model/VoiceFileDownloader.model.js.map +1 -1
- package/dist/commonjs/features/voice/playing/model/VoicePlayer.model.js +46 -172
- package/dist/commonjs/features/voice/playing/model/VoicePlayer.model.js.map +1 -1
- package/dist/commonjs/features/voice/types.js.map +1 -1
- package/dist/commonjs/index.js +12 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/module/features/translation/constants.js +7 -0
- package/dist/module/features/translation/constants.js.map +1 -0
- package/dist/module/features/translation/helpers.js +53 -0
- package/dist/module/features/translation/helpers.js.map +1 -0
- package/dist/module/features/translation/index.js +12 -0
- package/dist/module/features/translation/index.js.map +1 -0
- package/dist/module/features/translation/model/TranslationModel.js +117 -0
- package/dist/module/features/translation/model/TranslationModel.js.map +1 -0
- package/dist/module/features/translation/model/TranslationPreprocessor.js +137 -0
- package/dist/module/features/translation/model/TranslationPreprocessor.js.map +1 -0
- package/dist/module/features/translation/model/TranslationService.js +107 -0
- package/dist/module/features/translation/model/TranslationService.js.map +1 -0
- package/dist/module/features/translation/preserve/wordsToPreserve.js +310 -0
- package/dist/module/features/translation/preserve/wordsToPreserve.js.map +1 -0
- package/dist/module/features/translation/providers/google/GoogleTranslationProvider.js +45 -0
- package/dist/module/features/translation/providers/google/GoogleTranslationProvider.js.map +1 -0
- package/dist/module/features/translation/providers/google/supportedLanguages.js +225 -0
- package/dist/module/features/translation/providers/google/supportedLanguages.js.map +1 -0
- package/dist/module/features/translation/providers/google.types.js +2 -0
- package/dist/module/features/translation/providers/google.types.js.map +1 -0
- package/dist/module/features/translation/providers/translation.interface.js +44 -0
- package/dist/module/features/translation/providers/translation.interface.js.map +1 -0
- package/dist/module/features/translation/types.js +2 -0
- package/dist/module/features/translation/types.js.map +1 -0
- package/dist/module/features/voice/index.js +1 -1
- package/dist/module/features/voice/index.js.map +1 -1
- package/dist/module/features/voice/playing/components/VoiceTranscriptContent.js +38 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptContent.js.map +1 -0
- package/dist/module/features/voice/playing/components/VoiceTranscription.js +101 -0
- package/dist/module/features/voice/playing/components/VoiceTranscription.js.map +1 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptionCollapsible.js +58 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptionCollapsible.js.map +1 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptionHeaderActions.js +52 -0
- package/dist/module/features/voice/playing/components/VoiceTranscriptionHeaderActions.js.map +1 -0
- package/dist/module/features/voice/playing/hooks/{useVoiceTranscriptionsDropdown.js → useDropdownAnimation.js} +6 -5
- package/dist/module/features/voice/playing/hooks/useDropdownAnimation.js.map +1 -0
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionController.js +123 -0
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionController.js.map +1 -0
- package/dist/module/features/voice/playing/model/{VoiceTranscriptionsDropdown.model.js → Dropdown.model.js} +2 -2
- package/dist/module/features/voice/playing/model/Dropdown.model.js.map +1 -0
- package/dist/module/features/voice/playing/model/PlaybackController.js +178 -0
- package/dist/module/features/voice/playing/model/PlaybackController.js.map +1 -0
- package/dist/module/features/voice/playing/model/Player.model.js +24 -1
- package/dist/module/features/voice/playing/model/Player.model.js.map +1 -1
- package/dist/module/features/voice/playing/model/{VoiceTranscriptionsCollection.js → TranscriptionsCollection.js} +2 -2
- package/dist/module/features/voice/playing/model/TranscriptionsCollection.js.map +1 -0
- package/dist/module/features/voice/playing/model/TranscriptionsDownloader.model.js +77 -0
- package/dist/module/features/voice/playing/model/TranscriptionsDownloader.model.js.map +1 -0
- package/dist/module/features/voice/playing/model/Translation.model.js +57 -0
- package/dist/module/features/voice/playing/model/Translation.model.js.map +1 -0
- package/dist/module/features/voice/playing/model/VoiceFileDownloader.model.js +2 -2
- package/dist/module/features/voice/playing/model/VoiceFileDownloader.model.js.map +1 -1
- package/dist/module/features/voice/playing/model/VoicePlayer.model.js +48 -174
- package/dist/module/features/voice/playing/model/VoicePlayer.model.js.map +1 -1
- package/dist/module/features/voice/types.js.map +1 -1
- package/dist/module/index.js +1 -0
- package/dist/module/index.js.map +1 -1
- package/dist/typescript/commonjs/features/translation/constants.d.ts +5 -0
- package/dist/typescript/commonjs/features/translation/constants.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/helpers.d.ts +9 -0
- package/dist/typescript/commonjs/features/translation/helpers.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/index.d.ts +12 -0
- package/dist/typescript/commonjs/features/translation/index.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/model/TranslationModel.d.ts +33 -0
- package/dist/typescript/commonjs/features/translation/model/TranslationModel.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/model/TranslationPreprocessor.d.ts +34 -0
- package/dist/typescript/commonjs/features/translation/model/TranslationPreprocessor.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/model/TranslationService.d.ts +40 -0
- package/dist/typescript/commonjs/features/translation/model/TranslationService.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/preserve/wordsToPreserve.d.ts +3 -0
- package/dist/typescript/commonjs/features/translation/preserve/wordsToPreserve.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/providers/google/GoogleTranslationProvider.d.ts +17 -0
- package/dist/typescript/commonjs/features/translation/providers/google/GoogleTranslationProvider.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/providers/google/supportedLanguages.d.ts +209 -0
- package/dist/typescript/commonjs/features/translation/providers/google/supportedLanguages.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/providers/google.types.d.ts +15 -0
- package/dist/typescript/commonjs/features/translation/providers/google.types.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/providers/translation.interface.d.ts +30 -0
- package/dist/typescript/commonjs/features/translation/providers/translation.interface.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/translation/types.d.ts +27 -0
- package/dist/typescript/commonjs/features/translation/types.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/index.d.ts +2 -1
- package/dist/typescript/commonjs/features/voice/index.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptContent.d.ts +8 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptContent.d.ts.map +1 -0
- package/dist/typescript/{module/features/voice/playing/components/VoiceTranscriptionsDropdown.d.ts → commonjs/features/voice/playing/components/VoiceTranscription.d.ts} +3 -4
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscription.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionCollapsible.d.ts +10 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionCollapsible.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionHeaderActions.d.ts +12 -0
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionHeaderActions.d.ts.map +1 -0
- package/dist/typescript/{module/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.d.ts → commonjs/features/voice/playing/hooks/useDropdownAnimation.d.ts} +3 -3
- package/dist/typescript/commonjs/features/voice/playing/hooks/useDropdownAnimation.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionController.d.ts +30 -0
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionController.d.ts.map +1 -0
- package/dist/typescript/{module/features/voice/playing/model/VoiceTranscriptionsDropdown.model.d.ts → commonjs/features/voice/playing/model/Dropdown.model.d.ts} +2 -2
- package/dist/typescript/commonjs/features/voice/playing/model/Dropdown.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/PlaybackController.d.ts +28 -0
- package/dist/typescript/commonjs/features/voice/playing/model/PlaybackController.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/Player.model.d.ts +3 -0
- package/dist/typescript/commonjs/features/voice/playing/model/Player.model.d.ts.map +1 -1
- package/dist/typescript/{module/features/voice/playing/model/VoiceTranscriptionsCollection.d.ts → commonjs/features/voice/playing/model/TranscriptionsCollection.d.ts} +2 -2
- package/dist/typescript/commonjs/features/voice/playing/model/TranscriptionsCollection.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/TranscriptionsDownloader.model.d.ts +19 -0
- package/dist/typescript/commonjs/features/voice/playing/model/TranscriptionsDownloader.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/Translation.model.d.ts +25 -0
- package/dist/typescript/commonjs/features/voice/playing/model/Translation.model.d.ts.map +1 -0
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceFileDownloader.model.d.ts +2 -2
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceFileDownloader.model.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/voice/playing/model/VoicePlayer.model.d.ts +18 -18
- package/dist/typescript/commonjs/features/voice/playing/model/VoicePlayer.model.d.ts.map +1 -1
- package/dist/typescript/commonjs/features/voice/types.d.ts +5 -1
- package/dist/typescript/commonjs/features/voice/types.d.ts.map +1 -1
- package/dist/typescript/commonjs/index.d.ts +1 -0
- package/dist/typescript/commonjs/index.d.ts.map +1 -1
- package/dist/typescript/module/features/translation/constants.d.ts +5 -0
- package/dist/typescript/module/features/translation/constants.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/helpers.d.ts +9 -0
- package/dist/typescript/module/features/translation/helpers.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/index.d.ts +12 -0
- package/dist/typescript/module/features/translation/index.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/model/TranslationModel.d.ts +33 -0
- package/dist/typescript/module/features/translation/model/TranslationModel.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/model/TranslationPreprocessor.d.ts +34 -0
- package/dist/typescript/module/features/translation/model/TranslationPreprocessor.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/model/TranslationService.d.ts +40 -0
- package/dist/typescript/module/features/translation/model/TranslationService.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/preserve/wordsToPreserve.d.ts +3 -0
- package/dist/typescript/module/features/translation/preserve/wordsToPreserve.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/providers/google/GoogleTranslationProvider.d.ts +17 -0
- package/dist/typescript/module/features/translation/providers/google/GoogleTranslationProvider.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/providers/google/supportedLanguages.d.ts +209 -0
- package/dist/typescript/module/features/translation/providers/google/supportedLanguages.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/providers/google.types.d.ts +15 -0
- package/dist/typescript/module/features/translation/providers/google.types.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/providers/translation.interface.d.ts +30 -0
- package/dist/typescript/module/features/translation/providers/translation.interface.d.ts.map +1 -0
- package/dist/typescript/module/features/translation/types.d.ts +27 -0
- package/dist/typescript/module/features/translation/types.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/index.d.ts +2 -1
- package/dist/typescript/module/features/voice/index.d.ts.map +1 -1
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptContent.d.ts +8 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptContent.d.ts.map +1 -0
- package/dist/typescript/{commonjs/features/voice/playing/components/VoiceTranscriptionsDropdown.d.ts → module/features/voice/playing/components/VoiceTranscription.d.ts} +3 -4
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscription.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionCollapsible.d.ts +10 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionCollapsible.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionHeaderActions.d.ts +12 -0
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionHeaderActions.d.ts.map +1 -0
- package/dist/typescript/{commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.d.ts → module/features/voice/playing/hooks/useDropdownAnimation.d.ts} +3 -3
- package/dist/typescript/module/features/voice/playing/hooks/useDropdownAnimation.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionController.d.ts +30 -0
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionController.d.ts.map +1 -0
- package/dist/typescript/{commonjs/features/voice/playing/model/VoiceTranscriptionsDropdown.model.d.ts → module/features/voice/playing/model/Dropdown.model.d.ts} +2 -2
- package/dist/typescript/module/features/voice/playing/model/Dropdown.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/PlaybackController.d.ts +28 -0
- package/dist/typescript/module/features/voice/playing/model/PlaybackController.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/Player.model.d.ts +3 -0
- package/dist/typescript/module/features/voice/playing/model/Player.model.d.ts.map +1 -1
- package/dist/typescript/{commonjs/features/voice/playing/model/VoiceTranscriptionsCollection.d.ts → module/features/voice/playing/model/TranscriptionsCollection.d.ts} +2 -2
- package/dist/typescript/module/features/voice/playing/model/TranscriptionsCollection.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/TranscriptionsDownloader.model.d.ts +19 -0
- package/dist/typescript/module/features/voice/playing/model/TranscriptionsDownloader.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/Translation.model.d.ts +25 -0
- package/dist/typescript/module/features/voice/playing/model/Translation.model.d.ts.map +1 -0
- package/dist/typescript/module/features/voice/playing/model/VoiceFileDownloader.model.d.ts +2 -2
- package/dist/typescript/module/features/voice/playing/model/VoiceFileDownloader.model.d.ts.map +1 -1
- package/dist/typescript/module/features/voice/playing/model/VoicePlayer.model.d.ts +18 -18
- package/dist/typescript/module/features/voice/playing/model/VoicePlayer.model.d.ts.map +1 -1
- package/dist/typescript/module/features/voice/types.d.ts +5 -1
- package/dist/typescript/module/features/voice/types.d.ts.map +1 -1
- package/dist/typescript/module/index.d.ts +1 -0
- package/dist/typescript/module/index.d.ts.map +1 -1
- package/package.json +28 -1
- package/src/features/translation/constants.ts +4 -0
- package/src/features/translation/helpers.ts +63 -0
- package/src/features/translation/index.ts +30 -0
- package/src/features/translation/model/TranslationModel.ts +174 -0
- package/src/features/translation/model/TranslationPreprocessor.ts +171 -0
- package/src/features/translation/model/TranslationService.ts +148 -0
- package/src/features/translation/preserve/wordsToPreserve.ts +87 -0
- package/src/features/translation/providers/google/GoogleTranslationProvider.ts +50 -0
- package/src/features/translation/providers/google/supportedLanguages.ts +229 -0
- package/src/features/translation/providers/google.types.ts +16 -0
- package/src/features/translation/providers/translation.interface.ts +63 -0
- package/src/features/translation/types.ts +30 -0
- package/src/features/voice/index.ts +2 -1
- package/src/features/voice/playing/components/VoiceTranscriptContent.tsx +37 -0
- package/src/features/voice/playing/components/VoiceTranscription.tsx +117 -0
- package/src/features/voice/playing/components/VoiceTranscriptionCollapsible.tsx +59 -0
- package/src/features/voice/playing/components/VoiceTranscriptionHeaderActions.tsx +61 -0
- package/src/features/voice/playing/hooks/{useVoiceTranscriptionsDropdown.ts → useDropdownAnimation.ts} +5 -5
- package/src/features/voice/playing/hooks/useVoiceTranscriptionController.ts +171 -0
- package/src/features/voice/playing/model/{VoiceTranscriptionsDropdown.model.ts → Dropdown.model.ts} +2 -2
- package/src/features/voice/playing/model/PlaybackController.ts +213 -0
- package/src/features/voice/playing/model/Player.model.ts +26 -1
- package/src/features/voice/playing/model/{VoiceTranscriptionsCollection.ts → TranscriptionsCollection.ts} +1 -1
- package/src/features/voice/playing/model/TranscriptionsDownloader.model.ts +88 -0
- package/src/features/voice/playing/model/Translation.model.ts +75 -0
- package/src/features/voice/playing/model/VoiceFileDownloader.model.ts +2 -2
- package/src/features/voice/playing/model/VoicePlayer.model.ts +57 -194
- package/src/features/voice/types.ts +10 -0
- package/src/index.ts +1 -0
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdown.js +0 -251
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdown.js.map +0 -1
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdownItem.js +0 -109
- package/dist/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdownItem.js.map +0 -1
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.js.map +0 -1
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.js +0 -34
- package/dist/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.js.map +0 -1
- package/dist/commonjs/features/voice/playing/model/TranscriptionsDownloaderModel.js +0 -66
- package/dist/commonjs/features/voice/playing/model/TranscriptionsDownloaderModel.js.map +0 -1
- package/dist/commonjs/features/voice/playing/model/VoiceTranscriptionsCollection.js.map +0 -1
- package/dist/commonjs/features/voice/playing/model/VoiceTranscriptionsDropdown.model.js.map +0 -1
- package/dist/module/features/voice/playing/components/VoiceTranscriptionsDropdown.js +0 -244
- package/dist/module/features/voice/playing/components/VoiceTranscriptionsDropdown.js.map +0 -1
- package/dist/module/features/voice/playing/components/VoiceTranscriptionsDropdownItem.js +0 -103
- package/dist/module/features/voice/playing/components/VoiceTranscriptionsDropdownItem.js.map +0 -1
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.js.map +0 -1
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.js +0 -29
- package/dist/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.js.map +0 -1
- package/dist/module/features/voice/playing/model/TranscriptionsDownloaderModel.js +0 -61
- package/dist/module/features/voice/playing/model/TranscriptionsDownloaderModel.js.map +0 -1
- package/dist/module/features/voice/playing/model/VoiceTranscriptionsCollection.js.map +0 -1
- package/dist/module/features/voice/playing/model/VoiceTranscriptionsDropdown.model.js.map +0 -1
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdown.d.ts.map +0 -1
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdownItem.d.ts +0 -12
- package/dist/typescript/commonjs/features/voice/playing/components/VoiceTranscriptionsDropdownItem.d.ts.map +0 -1
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.d.ts.map +0 -1
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.d.ts +0 -11
- package/dist/typescript/commonjs/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.d.ts.map +0 -1
- package/dist/typescript/commonjs/features/voice/playing/model/TranscriptionsDownloaderModel.d.ts +0 -15
- package/dist/typescript/commonjs/features/voice/playing/model/TranscriptionsDownloaderModel.d.ts.map +0 -1
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceTranscriptionsCollection.d.ts.map +0 -1
- package/dist/typescript/commonjs/features/voice/playing/model/VoiceTranscriptionsDropdown.model.d.ts.map +0 -1
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionsDropdown.d.ts.map +0 -1
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionsDropdownItem.d.ts +0 -12
- package/dist/typescript/module/features/voice/playing/components/VoiceTranscriptionsDropdownItem.d.ts.map +0 -1
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdown.d.ts.map +0 -1
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.d.ts +0 -11
- package/dist/typescript/module/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.d.ts.map +0 -1
- package/dist/typescript/module/features/voice/playing/model/TranscriptionsDownloaderModel.d.ts +0 -15
- package/dist/typescript/module/features/voice/playing/model/TranscriptionsDownloaderModel.d.ts.map +0 -1
- package/dist/typescript/module/features/voice/playing/model/VoiceTranscriptionsCollection.d.ts.map +0 -1
- package/dist/typescript/module/features/voice/playing/model/VoiceTranscriptionsDropdown.model.d.ts.map +0 -1
- package/src/features/voice/playing/components/VoiceTranscriptionsDropdown.tsx +0 -302
- package/src/features/voice/playing/components/VoiceTranscriptionsDropdownItem.tsx +0 -128
- package/src/features/voice/playing/hooks/useVoiceTranscriptionsDropdownItemAnimation.ts +0 -40
- package/src/features/voice/playing/model/TranscriptionsDownloaderModel.ts +0 -80
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attach,
|
|
3
|
+
combine,
|
|
4
|
+
createEffect,
|
|
5
|
+
createEvent,
|
|
6
|
+
restore,
|
|
7
|
+
sample,
|
|
8
|
+
split,
|
|
9
|
+
Store,
|
|
10
|
+
Unit,
|
|
11
|
+
} from 'effector'
|
|
12
|
+
import { GoogleTranslationProvider } from '../providers/google/GoogleTranslationProvider'
|
|
13
|
+
import {
|
|
14
|
+
GoogleTranslateProps,
|
|
15
|
+
GoogleTranslateResponse,
|
|
16
|
+
} from '../providers/google.types'
|
|
17
|
+
import { TranslationService } from './TranslationService'
|
|
18
|
+
import {
|
|
19
|
+
preservedWordsReplacers,
|
|
20
|
+
wordsToPreserve,
|
|
21
|
+
} from '../preserve/wordsToPreserve'
|
|
22
|
+
import {
|
|
23
|
+
CHOICES_CACHE_KEY_SUFFIX,
|
|
24
|
+
DESCRIPTION_CACHE_KEY_SUFFIX,
|
|
25
|
+
GBD_TEXT_CACHE_SUFFIX,
|
|
26
|
+
} from '../constants'
|
|
27
|
+
import {
|
|
28
|
+
TranslatableProblem,
|
|
29
|
+
TranslateAllFxParams,
|
|
30
|
+
TranslateFxParams,
|
|
31
|
+
} from '../types'
|
|
32
|
+
|
|
33
|
+
type TranslationModelProps<TProblem extends TranslatableProblem> = {
|
|
34
|
+
$problem: Store<TProblem | null>
|
|
35
|
+
$problemId: Store<string>
|
|
36
|
+
$assignmentId: Store<string>
|
|
37
|
+
$currentProblemIndex: Store<number>
|
|
38
|
+
$translationLanguageCode: Store<string>
|
|
39
|
+
$contentLanguageCode?: Store<string>
|
|
40
|
+
$isTranslationLocked: Store<boolean>
|
|
41
|
+
languageChanged: Unit<unknown>
|
|
42
|
+
api: {
|
|
43
|
+
translateRequest: (payload: GoogleTranslateProps) => Promise<GoogleTranslateResponse>
|
|
44
|
+
}
|
|
45
|
+
getGreatWorkFeedbackText?: () => string
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class TranslationModel<TProblem extends TranslatableProblem = TranslatableProblem> {
|
|
49
|
+
private readonly service: TranslationService
|
|
50
|
+
|
|
51
|
+
public readonly toggle = createEvent()
|
|
52
|
+
public readonly setTranslated = createEvent<boolean>()
|
|
53
|
+
public readonly reset = createEvent()
|
|
54
|
+
|
|
55
|
+
public readonly $isTranslationActive = restore(this.setTranslated, false).reset(this.reset)
|
|
56
|
+
public readonly $isTranslated = this.$isTranslationActive
|
|
57
|
+
public readonly $isTranslationPending
|
|
58
|
+
|
|
59
|
+
public readonly translateFx
|
|
60
|
+
public readonly translateAllFx
|
|
61
|
+
|
|
62
|
+
constructor({
|
|
63
|
+
$problem,
|
|
64
|
+
$problemId,
|
|
65
|
+
$assignmentId,
|
|
66
|
+
$currentProblemIndex,
|
|
67
|
+
$translationLanguageCode,
|
|
68
|
+
$contentLanguageCode,
|
|
69
|
+
$isTranslationLocked,
|
|
70
|
+
languageChanged,
|
|
71
|
+
api,
|
|
72
|
+
getGreatWorkFeedbackText,
|
|
73
|
+
}: TranslationModelProps<TProblem>) {
|
|
74
|
+
this.service = new TranslationService({
|
|
75
|
+
preserve: {
|
|
76
|
+
map: wordsToPreserve,
|
|
77
|
+
replacers: preservedWordsReplacers,
|
|
78
|
+
},
|
|
79
|
+
providers: [new GoogleTranslationProvider({ api })],
|
|
80
|
+
onError: () => this.reset(),
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
this.service.bindCustomCacheKey(
|
|
84
|
+
$problemId,
|
|
85
|
+
(problemId, { target }) => `${problemId}::${target}`,
|
|
86
|
+
)
|
|
87
|
+
this.service.bindTargetLanguage($translationLanguageCode)
|
|
88
|
+
if ($contentLanguageCode) {
|
|
89
|
+
this.service.bindSourceLanguage($contentLanguageCode)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
this.translateAllFx = attach({
|
|
93
|
+
source: {
|
|
94
|
+
problem: $problem,
|
|
95
|
+
translationLanguageCode: $translationLanguageCode,
|
|
96
|
+
},
|
|
97
|
+
mapParams: (_: void, source) => source,
|
|
98
|
+
effect: createEffect(({ problem, translationLanguageCode }: TranslateAllFxParams<TProblem>) => {
|
|
99
|
+
if (!problem) return
|
|
100
|
+
|
|
101
|
+
const promises: Promise<unknown>[] = [
|
|
102
|
+
this.service.translate(problem.richDescription || problem.description, {
|
|
103
|
+
cacheKeySuffix: DESCRIPTION_CACHE_KEY_SUFFIX,
|
|
104
|
+
}),
|
|
105
|
+
this.service.translate(problem.answerVariants, {
|
|
106
|
+
cacheKeySuffix: CHOICES_CACHE_KEY_SUFFIX,
|
|
107
|
+
}),
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
if (getGreatWorkFeedbackText) {
|
|
111
|
+
promises.push(
|
|
112
|
+
this.service.translate(getGreatWorkFeedbackText(), {
|
|
113
|
+
cacheKey: `${translationLanguageCode}${GBD_TEXT_CACHE_SUFFIX}`,
|
|
114
|
+
}),
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return Promise.all(promises)
|
|
119
|
+
}),
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
this.translateFx = createEffect(({ cacheKey, text }: TranslateFxParams) => {
|
|
123
|
+
return this.service.translate(text, { cacheKey })
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
this.$isTranslationActive.on(this.translateAllFx.doneData, () => true)
|
|
127
|
+
this.$isTranslationActive.on(this.translateAllFx.fail, () => false)
|
|
128
|
+
|
|
129
|
+
split({
|
|
130
|
+
source: sample({
|
|
131
|
+
clock: this.toggle,
|
|
132
|
+
source: this.$isTranslationActive,
|
|
133
|
+
}),
|
|
134
|
+
match: {
|
|
135
|
+
on: (isTranslated) => !isTranslated,
|
|
136
|
+
off: (isTranslated) => isTranslated,
|
|
137
|
+
},
|
|
138
|
+
cases: {
|
|
139
|
+
on: this.translateAllFx,
|
|
140
|
+
off: this.reset,
|
|
141
|
+
},
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
sample({
|
|
145
|
+
clock: languageChanged,
|
|
146
|
+
fn: () => false,
|
|
147
|
+
target: this.setTranslated,
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
sample({
|
|
151
|
+
clock: [$currentProblemIndex, $assignmentId, this.$isTranslationActive],
|
|
152
|
+
source: {
|
|
153
|
+
isTranslated: this.$isTranslationActive,
|
|
154
|
+
isLocked: $isTranslationLocked,
|
|
155
|
+
},
|
|
156
|
+
filter: ({ isTranslated, isLocked }) => isLocked || isTranslated,
|
|
157
|
+
target: this.translateAllFx,
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
this.$isTranslationPending = combine(
|
|
161
|
+
this.translateAllFx.pending,
|
|
162
|
+
this.translateFx.pending,
|
|
163
|
+
(isAllPending, isOnePending) => isAllPending || isOnePending,
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public getTranslated<T extends string | string[]>(key: string): T | undefined {
|
|
168
|
+
return this.service.getCached<T>(key)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public clearCache() {
|
|
172
|
+
this.service.reset()
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { LanguageGlossary } from '../providers/translation.interface'
|
|
2
|
+
import { maskSegment, replaceMappedTokens } from '../helpers'
|
|
3
|
+
import { Replacement } from '../types'
|
|
4
|
+
|
|
5
|
+
const KATEX_REGEX = /\$(.+?)\$/g
|
|
6
|
+
const NEWLINE_REGEX = /\n/g
|
|
7
|
+
const QUOTE_REGEX = /\\(['"])/g
|
|
8
|
+
const DOLLAR_REGEX = /\\\$/gm
|
|
9
|
+
const COMMA_REGEX = /,/gm
|
|
10
|
+
const DOT_REGEX = /\./gm
|
|
11
|
+
|
|
12
|
+
const wrapNoTranslate = (content: string) => `<span translate="no">${content}</span>`
|
|
13
|
+
|
|
14
|
+
const KATEX_PLACEHOLDER = wrapNoTranslate('{{@}}')
|
|
15
|
+
const NEWLINE__PLACEHOLDER = wrapNoTranslate('{{#}}')
|
|
16
|
+
const QUOTE_PLACEHOLDER = wrapNoTranslate('{{""}}')
|
|
17
|
+
const DOLLAR_PLACEHOLDER = wrapNoTranslate('{{!}}')
|
|
18
|
+
const COMMA_PLACEHOLDER = wrapNoTranslate('{{,}}')
|
|
19
|
+
const DOT_PLACEHOLDER = wrapNoTranslate('{{.}}')
|
|
20
|
+
|
|
21
|
+
const defaultOrderedReplacersMap = [
|
|
22
|
+
[DOLLAR_REGEX, DOLLAR_PLACEHOLDER],
|
|
23
|
+
[KATEX_REGEX, KATEX_PLACEHOLDER],
|
|
24
|
+
[NEWLINE_REGEX, NEWLINE__PLACEHOLDER],
|
|
25
|
+
[QUOTE_REGEX, QUOTE_PLACEHOLDER],
|
|
26
|
+
[COMMA_REGEX, COMMA_PLACEHOLDER],
|
|
27
|
+
[DOT_REGEX, DOT_PLACEHOLDER],
|
|
28
|
+
] as const
|
|
29
|
+
|
|
30
|
+
type SetupPreservableProps = {
|
|
31
|
+
glossaryToPreserve: LanguageGlossary
|
|
32
|
+
preserveWordsReplacers: [RegExp, string][]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class TranslationKatexPreprocessor {
|
|
36
|
+
private static plaintextConverter: (text: string) => string = (text) => text
|
|
37
|
+
|
|
38
|
+
public static setPlaintextConverter(converter: (text: string) => string) {
|
|
39
|
+
this.plaintextConverter = converter
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public static shouldSkipTranslation(text: string | string[] = '') {
|
|
43
|
+
if (Array.isArray(text)) {
|
|
44
|
+
return text.every(
|
|
45
|
+
(t) => this.isMathExpressionOnly(t) || this.isSingleLetter(t) || this.isMathSymbolsOnly(t),
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
this.isMathExpressionOnly(text) || this.isSingleLetter(text) || this.isMathSymbolsOnly(text)
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public static isMathExpressionOnly(text: string) {
|
|
55
|
+
return /^[\d\s+\-*/^=().\\><%!|]+$/.test(text.trim())
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public static isSingleLetter(text: string) {
|
|
59
|
+
return /^[a-zA-Z]$/.test(text)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public static isMathSymbolsOnly(text: string) {
|
|
63
|
+
const plainText = this.plaintextConverter(text)
|
|
64
|
+
const cleanedUp = plainText.replace(/(\\\\|\\|\$|\−|\+|\=|\*|kr|pln|€|£|x|y|\{|\}|\÷)/gi, '')
|
|
65
|
+
const mathOnlyRegex = /^(?=.*\d)[0-9+\-×÷*/^().\s]+$/u
|
|
66
|
+
return cleanedUp.length > 0 && mathOnlyRegex.test(cleanedUp)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private globalTargetLanguage: string | null = null
|
|
70
|
+
private preserveWordsMap: LanguageGlossary = {}
|
|
71
|
+
private preserveWordsReplacers: [RegExp, string][] = []
|
|
72
|
+
|
|
73
|
+
private normalizePlaceholderSpacing(text: string) {
|
|
74
|
+
return text
|
|
75
|
+
.replace(/\s+(<span[^>]*translate="no"[^>]*>)/g, '$1')
|
|
76
|
+
.replace(/(<\/span>)\s+/g, '$1')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public sanitize(text: string): { sanitized: string; replacements: Replacement[] } {
|
|
80
|
+
const language = this.globalTargetLanguage ?? ''
|
|
81
|
+
const replacements: Replacement[] = []
|
|
82
|
+
let sanitizedText = text
|
|
83
|
+
|
|
84
|
+
defaultOrderedReplacersMap.forEach(([regex, placeholder]) => {
|
|
85
|
+
sanitizedText = maskSegment({
|
|
86
|
+
text: sanitizedText,
|
|
87
|
+
regex,
|
|
88
|
+
placeholder,
|
|
89
|
+
replacements,
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
this.preserveWordsReplacers.forEach(([regex, placeholder]) => {
|
|
94
|
+
const preserveWordsMapTarget = this.preserveWordsMap[language]
|
|
95
|
+
|
|
96
|
+
sanitizedText = maskSegment({
|
|
97
|
+
text: sanitizedText,
|
|
98
|
+
regex,
|
|
99
|
+
placeholder,
|
|
100
|
+
replacements,
|
|
101
|
+
shouldSkip: (match) =>
|
|
102
|
+
this.skipCustomReplacerSanitizeWithoutGlossary(match, preserveWordsMapTarget),
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
return { sanitized: sanitizedText, replacements }
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public restore(text: string, replacements: Replacement[]) {
|
|
110
|
+
let restored = this.normalizePlaceholderSpacing(text)
|
|
111
|
+
replacements.forEach(({ placeholder, original, leftPad, rightPad }) => {
|
|
112
|
+
const wrapped = `${leftPad ? ' ' : ''}${original}${rightPad ? ' ' : ''}`
|
|
113
|
+
restored = restored.replace(placeholder, wrapped)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
return this.applyPreserved(restored)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public sanitizeBatch(texts: string[]): { sanitized: string[]; replacements: Replacement[][] } {
|
|
120
|
+
const sanitized: string[] = []
|
|
121
|
+
const replacements: Replacement[][] = []
|
|
122
|
+
|
|
123
|
+
texts.forEach((t) => {
|
|
124
|
+
const { sanitized: s, replacements: r } = this.sanitize(t)
|
|
125
|
+
sanitized.push(s)
|
|
126
|
+
replacements.push(r)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
return { sanitized, replacements }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public restoreBatch(texts: string[], replacementsArray: Replacement[][]) {
|
|
133
|
+
return texts.map((t, i) => {
|
|
134
|
+
const restored = this.restore(t, replacementsArray[i])
|
|
135
|
+
return this.applyPreserved(restored)
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Glossaries apply after translation response and do not remove words from payload.
|
|
140
|
+
// This replaces words from the string before sending request to API to completely avoid
|
|
141
|
+
// translating it. We use it to avoid "context localization" e.g. Google API changes numbers
|
|
142
|
+
// when units are passed and target language is from a different region. We must preserve
|
|
143
|
+
// words like "miles" and the exact number in this case.
|
|
144
|
+
public setupPreservable({ glossaryToPreserve, preserveWordsReplacers }: SetupPreservableProps) {
|
|
145
|
+
this.preserveWordsMap = glossaryToPreserve
|
|
146
|
+
this.preserveWordsReplacers = preserveWordsReplacers
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public setupTarget(language: string) {
|
|
150
|
+
this.globalTargetLanguage = language
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private skipCustomReplacerSanitizeWithoutGlossary(
|
|
154
|
+
match: string,
|
|
155
|
+
preserveWordsMapTarget?: Record<string, string>,
|
|
156
|
+
) {
|
|
157
|
+
if (!preserveWordsMapTarget) return true
|
|
158
|
+
|
|
159
|
+
const normalized = match.toLowerCase()
|
|
160
|
+
const glossaryKeys = Object.keys(preserveWordsMapTarget).map((key) => key.toLowerCase())
|
|
161
|
+
|
|
162
|
+
return !glossaryKeys.includes(normalized)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private applyPreserved(restored: string) {
|
|
166
|
+
const language = this.globalTargetLanguage ?? ''
|
|
167
|
+
const preservedMap = this.preserveWordsMap[language]
|
|
168
|
+
|
|
169
|
+
return preservedMap ? replaceMappedTokens(restored, preservedMap) : restored
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Store } from 'effector'
|
|
2
|
+
import { TranslationKatexPreprocessor } from './TranslationPreprocessor'
|
|
3
|
+
import { LanguageGlossary, TranslationProvider } from '../providers/translation.interface'
|
|
4
|
+
|
|
5
|
+
type TranslationServiceProps = {
|
|
6
|
+
providers: TranslationProvider[]
|
|
7
|
+
preserve?: {
|
|
8
|
+
map: LanguageGlossary
|
|
9
|
+
replacers: [RegExp, string][]
|
|
10
|
+
}
|
|
11
|
+
onError?: () => void
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type TranslateConfigProps = {
|
|
15
|
+
targetLang?: string
|
|
16
|
+
sourceLang?: string
|
|
17
|
+
cacheKeySuffix?: string
|
|
18
|
+
cacheKey?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class TranslationService {
|
|
22
|
+
private readonly preprocessor = new TranslationKatexPreprocessor()
|
|
23
|
+
private readonly cache = new Map<string, string | string[]>()
|
|
24
|
+
private readonly providers: TranslationProvider[] = []
|
|
25
|
+
private readonly onError
|
|
26
|
+
|
|
27
|
+
private globalTargetLanguage: string | null = null
|
|
28
|
+
private sourceLanguage: string | null = null
|
|
29
|
+
private customCacheKeyFn: ((text: string | string[], target: string) => string) | null = null
|
|
30
|
+
|
|
31
|
+
constructor({ providers, preserve, onError }: TranslationServiceProps) {
|
|
32
|
+
this.providers = providers
|
|
33
|
+
this.onError = onError
|
|
34
|
+
|
|
35
|
+
if (preserve) {
|
|
36
|
+
this.preprocessor.setupPreservable({
|
|
37
|
+
glossaryToPreserve: preserve.map,
|
|
38
|
+
preserveWordsReplacers: preserve.replacers,
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private getTargetLanguage(targetLang?: string) {
|
|
44
|
+
const target = targetLang || this.globalTargetLanguage
|
|
45
|
+
if (!target) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
'Target language is missing, either provide in arguments or use .bindTargetLanguage()',
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
return target
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private getProvider(target: string) {
|
|
54
|
+
const provider = this.providers.find((svc) => svc.isTargetSupported(target))
|
|
55
|
+
if (!provider) throw new Error(`This target language: "${target}" is not supported.`)
|
|
56
|
+
return provider
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private createCacheKey(text: string | string[], target: string, suffix?: string) {
|
|
60
|
+
let baseKey: string
|
|
61
|
+
|
|
62
|
+
if (this.customCacheKeyFn) {
|
|
63
|
+
baseKey = this.customCacheKeyFn(text, target)
|
|
64
|
+
} else {
|
|
65
|
+
baseKey = Array.isArray(text) ? `${JSON.stringify(text)}::${target}` : `${text}::${target}`
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return suffix ? `${baseKey}${suffix}` : baseKey
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public translate = async <T extends string | string[]>(
|
|
72
|
+
text: T = '' as T,
|
|
73
|
+
config?: TranslateConfigProps,
|
|
74
|
+
): Promise<T> => {
|
|
75
|
+
const isArrayInput = Array.isArray(text)
|
|
76
|
+
const target = this.getTargetLanguage(config?.targetLang) ?? ''
|
|
77
|
+
|
|
78
|
+
if (!text.length || TranslationKatexPreprocessor.shouldSkipTranslation(text)) {
|
|
79
|
+
const key = config?.cacheKey ?? this.createCacheKey(text, target, config?.cacheKeySuffix)
|
|
80
|
+
if (this.cache.has(key)) return this.cache.get(key) as T
|
|
81
|
+
|
|
82
|
+
return text
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const source = config?.sourceLang ?? this.sourceLanguage ?? undefined
|
|
86
|
+
const provider = this.getProvider(target)
|
|
87
|
+
const key = config?.cacheKey ?? this.createCacheKey(text, target, config?.cacheKeySuffix)
|
|
88
|
+
|
|
89
|
+
if (this.cache.has(key)) return this.cache.get(key) as T
|
|
90
|
+
|
|
91
|
+
let translated: string | string[]
|
|
92
|
+
|
|
93
|
+
if (isArrayInput) {
|
|
94
|
+
const { sanitized, replacements } = this.preprocessor.sanitizeBatch(text)
|
|
95
|
+
const response = await provider.requestBatch(sanitized, target, source)
|
|
96
|
+
translated = this.preprocessor.restoreBatch(response, replacements)
|
|
97
|
+
} else {
|
|
98
|
+
const { sanitized, replacements } = this.preprocessor.sanitize(text)
|
|
99
|
+
const response = await provider.request(sanitized, target, source)
|
|
100
|
+
translated = this.preprocessor.restore(response, replacements)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.cache.set(key, translated)
|
|
104
|
+
|
|
105
|
+
return translated as T
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public bindTargetLanguage<T extends string>(
|
|
109
|
+
store: Store<T>,
|
|
110
|
+
callback?: (value: T) => string,
|
|
111
|
+
): this {
|
|
112
|
+
store.watch((t) => {
|
|
113
|
+
const value = callback ? callback(t) : t
|
|
114
|
+
this.globalTargetLanguage = value
|
|
115
|
+
this.preprocessor.setupTarget(value)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
return this
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public bindSourceLanguage<T extends string>(store: Store<T>): this {
|
|
122
|
+
store.watch((value) => {
|
|
123
|
+
this.sourceLanguage = value
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
return this
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public bindCustomCacheKey<T extends string>(
|
|
130
|
+
store: Store<T>,
|
|
131
|
+
callback: (value: T, input: { text: string | string[]; target: string }) => string,
|
|
132
|
+
): this {
|
|
133
|
+
store.watch((t) => {
|
|
134
|
+
this.customCacheKeyFn = (text: string | string[], target: string) =>
|
|
135
|
+
callback(t, { text, target })
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
return this
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public getCached<T extends string | string[]>(key: string): T | undefined {
|
|
142
|
+
return this.cache.get(key) as T | undefined
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public reset() {
|
|
146
|
+
this.cache.clear()
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export const wordsToPreserve: Record<string, Record<string, string>> = {
|
|
2
|
+
es: { mile: 'milla', miles: 'millas' },
|
|
3
|
+
hy: { mile: 'մղոն', miles: 'մղոններ' },
|
|
4
|
+
fr: { mile: 'mille', miles: 'milles' },
|
|
5
|
+
ru: { mile: 'миля', miles: 'мили' },
|
|
6
|
+
ar: { mile: 'ميل', miles: 'أميال' },
|
|
7
|
+
is: { mile: 'míla', miles: 'mílur' },
|
|
8
|
+
ja: { mile: 'マイル', miles: 'マイル' },
|
|
9
|
+
'zh-Hans': { mile: '英里', miles: '英里' },
|
|
10
|
+
af: { mile: 'myl', miles: 'myls' },
|
|
11
|
+
ko: { mile: '마일', miles: '마일' },
|
|
12
|
+
de: { mile: 'Meile', miles: 'Meilen' },
|
|
13
|
+
zu: { mile: 'ileyili', miles: 'amayela' },
|
|
14
|
+
'zh-Hant': { mile: '英里', miles: '英里' },
|
|
15
|
+
it: { mile: 'miglio', miles: 'miglia' },
|
|
16
|
+
ht: { mile: 'miy', miles: 'miy' },
|
|
17
|
+
hi: { mile: 'मील', miles: 'मील' },
|
|
18
|
+
pt: { mile: 'milha', miles: 'milhas' },
|
|
19
|
+
sq: { mile: 'milje', miles: 'milje' },
|
|
20
|
+
el: { mile: 'μίλι', miles: 'μίλια' },
|
|
21
|
+
pl: { mile: 'mila', miles: 'mile' },
|
|
22
|
+
te: { mile: 'మైలు', miles: 'మైలులు' },
|
|
23
|
+
am: { mile: 'ማይል', miles: 'ማይሎች' },
|
|
24
|
+
ta: { mile: 'மைல்', miles: 'மைல்கள்' },
|
|
25
|
+
vi: { mile: 'dặm', miles: 'dặm' },
|
|
26
|
+
uk: { mile: 'миля', miles: 'милі' },
|
|
27
|
+
haw: { mile: 'maila', miles: 'maila' },
|
|
28
|
+
sv: { mile: 'mile', miles: 'miles' },
|
|
29
|
+
bn: { mile: 'মাইল', miles: 'মাইল' },
|
|
30
|
+
tl: { mile: 'milya', miles: 'milya' },
|
|
31
|
+
ga: { mile: 'míle', miles: 'míleanna' },
|
|
32
|
+
nl: { mile: 'mijl', miles: 'mijlen' },
|
|
33
|
+
ur: { mile: 'میل', miles: 'میل' },
|
|
34
|
+
ee: { mile: 'maili', miles: 'maili' },
|
|
35
|
+
en: { mile: 'mile', miles: 'miles' },
|
|
36
|
+
az: { mile: 'mil', miles: 'mil' },
|
|
37
|
+
gu: { mile: 'માઈલ', miles: 'માઈલ્સ' },
|
|
38
|
+
ml: { mile: 'മൈൽ', miles: 'മൈലുകൾ' },
|
|
39
|
+
pa: { mile: 'ਮਾਈਲ', miles: 'ਮਾਈਲਾਂ' },
|
|
40
|
+
as: { mile: 'মাইল', miles: 'মাইল' },
|
|
41
|
+
bm: { mile: 'maili', miles: 'maili' },
|
|
42
|
+
he: { mile: 'מייל', miles: 'מיילים' },
|
|
43
|
+
fa: { mile: 'مایل', miles: 'مایلها' },
|
|
44
|
+
fi: { mile: 'maili', miles: 'mailia' },
|
|
45
|
+
tr: { mile: 'mil', miles: 'mil' },
|
|
46
|
+
da: { mile: 'mil', miles: 'mil' },
|
|
47
|
+
bg: { mile: 'миля', miles: 'мили' },
|
|
48
|
+
xh: { mile: 'imayile', miles: 'iimayile' },
|
|
49
|
+
yi: { mile: 'מייל', miles: 'מיילן' },
|
|
50
|
+
ps: { mile: 'مایل', miles: 'مایلونه' },
|
|
51
|
+
mr: { mile: 'मैल', miles: 'मैले' },
|
|
52
|
+
eu: { mile: 'mila', miles: 'milak' },
|
|
53
|
+
bs: { mile: 'milja', miles: 'milje' },
|
|
54
|
+
cs: { mile: 'míle', miles: 'míle' },
|
|
55
|
+
yo: { mile: 'maili', miles: 'maili' },
|
|
56
|
+
ak: { mile: 'maili', miles: 'maili' },
|
|
57
|
+
ro: { mile: 'milă', miles: 'mile' },
|
|
58
|
+
mn: { mile: 'миль', miles: 'миль' },
|
|
59
|
+
bho: { mile: 'माइल', miles: 'माइल्स' },
|
|
60
|
+
ka: { mile: 'მილი', miles: 'მილი' },
|
|
61
|
+
ca: { mile: 'milla', miles: 'milles' },
|
|
62
|
+
be: { mile: 'міля', miles: 'мілі' },
|
|
63
|
+
sw: { mile: 'maili', miles: 'maili' },
|
|
64
|
+
eo: { mile: 'mejlo', miles: 'mejloj' },
|
|
65
|
+
th: { mile: 'ไมล์', miles: 'ไมล์' },
|
|
66
|
+
ay: { mile: 'maili', miles: 'maili' },
|
|
67
|
+
doi: { mile: 'माइल', miles: 'माइल्स' },
|
|
68
|
+
hr: { mile: 'milja', miles: 'milje' },
|
|
69
|
+
sm: { mile: 'maila', miles: 'maila' },
|
|
70
|
+
kn: { mile: 'ಮೈಲು', miles: 'ಮೈಲುಗಳು' },
|
|
71
|
+
et: { mile: 'miil', miles: 'miilid' },
|
|
72
|
+
ceb: { mile: 'milya', miles: 'milya' },
|
|
73
|
+
ig: { mile: 'maịlụ', miles: 'maịlụ' },
|
|
74
|
+
ne: { mile: 'माइल', miles: 'माइलहरू' },
|
|
75
|
+
uz: { mile: 'mil', miles: 'mil' },
|
|
76
|
+
cy: { mile: 'filltir', miles: 'mili' },
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const MILE_REGEX = /mile/gm
|
|
80
|
+
const MILE_PLACEHOLDER = '__!{21_37_70}!__'
|
|
81
|
+
const MILES_REGEX = /miles/gm
|
|
82
|
+
const MILES_PLACEHOLDER = '__!{21_37_69}!__'
|
|
83
|
+
|
|
84
|
+
export const preservedWordsReplacers: [RegExp, string][] = [
|
|
85
|
+
[MILES_REGEX, MILES_PLACEHOLDER],
|
|
86
|
+
[MILE_REGEX, MILE_PLACEHOLDER],
|
|
87
|
+
]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createEffect, Effect } from 'effector'
|
|
2
|
+
import { LanguageGlossary, TranslationProvider } from '../translation.interface'
|
|
3
|
+
import { GoogleTranslateLanguage, resolveGoogleLanguageCode } from './supportedLanguages'
|
|
4
|
+
import { GoogleTranslateProps, GoogleTranslateResponse } from '../google.types'
|
|
5
|
+
import { decodeHtmlEntities } from '../../helpers'
|
|
6
|
+
|
|
7
|
+
type GoogleTranslationProviderProps = {
|
|
8
|
+
api: {
|
|
9
|
+
translateRequest: (payload: GoogleTranslateProps) => Promise<GoogleTranslateResponse>
|
|
10
|
+
}
|
|
11
|
+
glossaries?: LanguageGlossary
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class GoogleTranslationProvider extends TranslationProvider {
|
|
15
|
+
private readonly getTranslationFx: Effect<GoogleTranslateProps, GoogleTranslateResponse>
|
|
16
|
+
|
|
17
|
+
constructor({ api, glossaries }: GoogleTranslationProviderProps) {
|
|
18
|
+
super({ supportedLanguages: Object.values(GoogleTranslateLanguage), glossaries })
|
|
19
|
+
this.getTranslationFx = createEffect(api.translateRequest)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public resolveLanguage(language: string): string | null {
|
|
23
|
+
return resolveGoogleLanguageCode(language)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async request(text: string, targetLanguage: string, sourceLanguage?: string) {
|
|
27
|
+
const resolvedTarget = this.resolveLanguage(targetLanguage) ?? targetLanguage
|
|
28
|
+
const resolvedSource = sourceLanguage ? this.resolveLanguage(sourceLanguage) ?? undefined : undefined
|
|
29
|
+
const response = await this.getTranslationFx({
|
|
30
|
+
text: [text],
|
|
31
|
+
targetLanguage: resolvedTarget,
|
|
32
|
+
sourceLanguage: resolvedSource,
|
|
33
|
+
})
|
|
34
|
+
const translated = response.data.translations[0]?.translatedText ?? ''
|
|
35
|
+
return this.applyGlossary(decodeHtmlEntities(translated), resolvedTarget)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public async requestBatch(text: string[], targetLanguage: string, sourceLanguage?: string) {
|
|
39
|
+
const resolvedTarget = this.resolveLanguage(targetLanguage) ?? targetLanguage
|
|
40
|
+
const resolvedSource = sourceLanguage ? this.resolveLanguage(sourceLanguage) ?? undefined : undefined
|
|
41
|
+
const response = await this.getTranslationFx({
|
|
42
|
+
text,
|
|
43
|
+
targetLanguage: resolvedTarget,
|
|
44
|
+
sourceLanguage: resolvedSource,
|
|
45
|
+
})
|
|
46
|
+
return response.data.translations.map(({ translatedText }) =>
|
|
47
|
+
this.applyGlossary(decodeHtmlEntities(translatedText), resolvedTarget),
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
}
|