Unverified Commit 52b12ed7 authored by Charlie.Wei's avatar Charlie.Wei Committed by GitHub

Voice audition (#2504)

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