Co-authored-by: luowei <glpat-EjySCyNjWiLqAED-YmwM> Co-authored-by: crazywoola <427733928@qq.com> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com>tags/0.5.7
| @@ -9,6 +9,7 @@ import { Speaker } from '@/app/components/base/icons/src/vender/solid/mediaAndDe | |||
| import ConfigContext from '@/context/debug-configuration' | |||
| import { languages } from '@/utils/language' | |||
| import { fetchAppVoices } from '@/service/apps' | |||
| import AudioBtn from '@/app/components/base/audio-btn' | |||
| const TextToSpeech: FC = () => { | |||
| const { t } = useTranslation() | |||
| @@ -20,19 +21,28 @@ const TextToSpeech: FC = () => { | |||
| const matched = pathname.match(/\/app\/([^/]+)/) | |||
| const appId = (matched?.length && matched[1]) ? matched[1] : '' | |||
| const language = textToSpeechConfig.language | |||
| const languageInfo = languages.find(i => i.value === textToSpeechConfig.language) | |||
| const voiceItems = useSWR({ appId, language }, fetchAppVoices).data | |||
| const voiceItem = voiceItems?.find(item => item.value === textToSpeechConfig.voice) | |||
| return ( | |||
| <Panel | |||
| title={ | |||
| <div className='flex items-center gap-2'> | |||
| <div className='flex items-center'> | |||
| <div>{t('appDebug.feature.textToSpeech.title')}</div> | |||
| </div> | |||
| } | |||
| headerIcon={<Speaker className='w-4 h-4 text-[#7839EE]' />} | |||
| headerRight={ | |||
| <div className='text-xs text-gray-500'> | |||
| {languages.find(i => i.value === textToSpeechConfig.language)?.name} - {voiceItem?.name ?? t('appDebug.voice.defaultDisplay')} | |||
| <div className='text-xs text-gray-500 inline-flex items-center gap-2'> | |||
| {languageInfo && (`${languageInfo?.name} - `)}{voiceItem?.name ?? t('appDebug.voice.defaultDisplay')} | |||
| { languageInfo?.example && ( | |||
| <AudioBtn | |||
| value={languageInfo?.example} | |||
| isAudition={true} | |||
| /> | |||
| )} | |||
| </div> | |||
| } | |||
| noBodySpacing | |||
| @@ -10,11 +10,13 @@ import { textToAudio } from '@/service/share' | |||
| type AudioBtnProps = { | |||
| value: string | |||
| className?: string | |||
| isAudition?: boolean | |||
| } | |||
| const AudioBtn = ({ | |||
| value, | |||
| className, | |||
| isAudition, | |||
| }: AudioBtnProps) => { | |||
| const audioRef = useRef<HTMLAudioElement | null>(null) | |||
| const [isPlaying, setIsPlaying] = useState(false) | |||
| @@ -97,10 +99,10 @@ const AudioBtn = ({ | |||
| className='z-10' | |||
| > | |||
| <div | |||
| className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'} | |||
| style={{ boxShadow: '0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06)' }} | |||
| className={`box-border p-0.5 flex items-center justify-center cursor-pointer ${isAudition || 'rounded-md bg-white'}`} | |||
| style={{ boxShadow: !isAudition ? '0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06)' : '' }} | |||
| onClick={togglePlayPause}> | |||
| <div className={`w-6 h-6 rounded-md hover:bg-gray-50 ${!isPause ? ((isPlaying && !hasEnded) ? s.playIcon : s.stopIcon) : s.pauseIcon}`}></div> | |||
| <div className={`w-6 h-6 rounded-md ${!isAudition ? 'hover:bg-gray-200' : 'hover:bg-gray-50'} ${!isPause ? ((isPlaying && !hasEnded) ? s.playIcon : s.stopIcon) : s.pauseIcon}`}></div> | |||
| </div> | |||
| </Tooltip> | |||
| </div> | |||
| @@ -53,6 +53,7 @@ const translation = { | |||
| koKR: 'Korean', | |||
| ptBR: 'Portuguese', | |||
| ruRU: 'Russian', | |||
| ukUA: 'Ukrainian', | |||
| }, | |||
| }, | |||
| unit: { | |||
| @@ -22,6 +22,7 @@ const translation = { | |||
| itIT: 'italiano', | |||
| thTH: 'tailandês', | |||
| idID: 'indonésio', | |||
| ukUA: 'ucraniana', | |||
| }, | |||
| }, | |||
| provider: { | |||
| @@ -53,6 +53,7 @@ const translation = { | |||
| koKR: '韩语', | |||
| ptBR: '葡萄牙语', | |||
| ruRU: '俄语', | |||
| ukUA: '乌克兰语', | |||
| }, | |||
| }, | |||
| unit: { | |||
| @@ -1,6 +1,7 @@ | |||
| export type Item = { | |||
| value: number | string | |||
| name: string | |||
| example: string | |||
| } | |||
| export const LanguagesSupported = ['en-US', 'zh-Hans', 'pt-BR', 'es-ES', 'fr-FR', 'de-DE', 'ja-JP', 'ko-KR', 'ru-RU', 'it-IT', 'th-TH', 'id-ID', 'uk-UA'] | |||
| @@ -10,54 +11,67 @@ export const languages = [ | |||
| { | |||
| value: 'en-US', | |||
| name: 'English(United States)', | |||
| example: 'Hello, Dify!', | |||
| }, | |||
| { | |||
| value: 'zh-Hans', | |||
| name: '简体中文', | |||
| example: '你好,Dify!', | |||
| }, | |||
| { | |||
| value: 'pt-BR', | |||
| name: 'Português(Brasil)', | |||
| example: 'Olá, Dify!', | |||
| }, | |||
| { | |||
| value: 'es-ES', | |||
| name: 'Español(España)', | |||
| example: 'Saluton, Dify!', | |||
| }, | |||
| { | |||
| value: 'fr-FR', | |||
| name: 'Français(France)', | |||
| example: 'Bonjour, Dify!', | |||
| }, | |||
| { | |||
| value: 'de-DE', | |||
| name: 'Deutsch(Deutschland)', | |||
| example: 'Hallo, Dify!', | |||
| }, | |||
| { | |||
| value: 'ja-JP', | |||
| name: '日本語(日本)', | |||
| example: 'こんにちは、Dify!', | |||
| }, | |||
| { | |||
| value: 'ko-KR', | |||
| name: '한국어(대한민국)', | |||
| example: '안녕, Dify!', | |||
| }, | |||
| { | |||
| value: 'ru-RU', | |||
| name: 'Русский(Россия)', | |||
| example: ' Привет, Dify!', | |||
| }, | |||
| { | |||
| value: 'it-IT', | |||
| name: 'Italiano(Italia)', | |||
| example: 'Ciao, Dify!', | |||
| }, | |||
| { | |||
| value: 'th-TH', | |||
| name: 'ไทย(ประเทศไทย)', | |||
| example: 'สวัสดี Dify!', | |||
| }, | |||
| { | |||
| value: 'id-ID', | |||
| name: 'Bahasa Indonesia', | |||
| example: 'Saluto, Dify!', | |||
| }, | |||
| { | |||
| value: 'uk-UA', | |||
| name: 'Українська(Україна)', | |||
| example: 'Привет, Dify!', | |||
| }, | |||
| ] | |||