Spaces:
Running
Running
| import { useEffect, useRef, useState } from 'react' | |
| import LanguageSelector from './components/LanguageSelector'; | |
| import Progress from './components/Progress'; | |
| import './App.css' | |
| function App() { | |
| // Model loading | |
| const [ready, setReady] = useState(null); | |
| const [disabled, setDisabled] = useState(false); | |
| const [progressItems, setProgressItems] = useState([]); | |
| // Inputs and outputs | |
| const [input, setInput] = useState('I love walking my dog.'); | |
| const [sourceLanguage, setSourceLanguage] = useState('eng_Latn'); | |
| const [targetLanguage, setTargetLanguage] = useState('fra_Latn'); | |
| const [output, setOutput] = useState(''); | |
| // Create a reference to the worker object. | |
| const worker = useRef(null); | |
| // We use the `useEffect` hook to setup the worker as soon as the `App` component is mounted. | |
| useEffect(() => { | |
| if (!worker.current) { | |
| // Create the worker if it does not yet exist. | |
| worker.current = new Worker(new URL('./worker.js', import.meta.url), { | |
| type: 'module' | |
| }); | |
| } | |
| // Create a callback function for messages from the worker thread. | |
| const onMessageReceived = (e) => { | |
| switch (e.data.status) { | |
| case 'initiate': | |
| // Model file start load: add a new progress item to the list. | |
| setReady(false); | |
| setProgressItems(prev => [...prev, e.data]); | |
| break; | |
| case 'progress': | |
| // Model file progress: update one of the progress items. | |
| setProgressItems( | |
| prev => prev.map(item => { | |
| if (item.file === e.data.file) { | |
| return { ...item, progress: e.data.progress } | |
| } | |
| return item; | |
| }) | |
| ); | |
| break; | |
| case 'done': | |
| // Model file loaded: remove the progress item from the list. | |
| setProgressItems( | |
| prev => prev.filter(item => item.file !== e.data.file) | |
| ); | |
| break; | |
| case 'ready': | |
| // Pipeline ready: the worker is ready to accept messages. | |
| setReady(true); | |
| break; | |
| case 'update': | |
| // Generation update: update the output text. | |
| setOutput(e.data.output); | |
| break; | |
| case 'complete': | |
| // Generation complete: re-enable the "Translate" button | |
| setDisabled(false); | |
| break; | |
| } | |
| }; | |
| // Attach the callback function as an event listener. | |
| worker.current.addEventListener('message', onMessageReceived); | |
| // Define a cleanup function for when the component is unmounted. | |
| return () => worker.current.removeEventListener('message', onMessageReceived); | |
| }); | |
| const translate = () => { | |
| setDisabled(true); | |
| worker.current.postMessage({ | |
| text: input, | |
| src_lang: sourceLanguage, | |
| tgt_lang: targetLanguage, | |
| }); | |
| } | |
| return ( | |
| <> | |
| <h1>Transformers.js</h1> | |
| <h2>ML-powered multilingual translation in React!</h2> | |
| <div className='container'> | |
| <div className='language-container'> | |
| <LanguageSelector type={"Source"} defaultLanguage={"eng_Latn"} onChange={x => setSourceLanguage(x.target.value)} /> | |
| <LanguageSelector type={"Target"} defaultLanguage={"fra_Latn"} onChange={x => setTargetLanguage(x.target.value)} /> | |
| </div> | |
| <div className='textbox-container'> | |
| <textarea value={input} rows={3} onChange={e => setInput(e.target.value)}></textarea> | |
| <textarea value={output} rows={3} readOnly></textarea> | |
| </div> | |
| </div> | |
| <button disabled={disabled} onClick={translate}>Translate</button> | |
| <div className='progress-bars-container'> | |
| {ready === false && ( | |
| <label>Loading models... (only run once)</label> | |
| )} | |
| {progressItems.map(data => ( | |
| <div key={data.file}> | |
| <Progress text={data.file} percentage={data.progress} /> | |
| </div> | |
| ))} | |
| </div> | |
| </> | |
| ) | |
| } | |
| export default App | |