Exemplos de API
Esta página contém exemplos completos de integração da API Rybená em diferentes frameworks e cenários de uso.
Integração por Framework
import { useEffect, useRef, useState } from 'react';
declare global {
interface Window {
RybenaApi?: {
getInstance: () => {
handleLoaded: (callback: () => void) => void;
openPlayer: () => void;
closePlayer: () => void;
translate: (text: string) => void;
switchToLibras: () => void;
switchToVoz: () => void;
pause: () => void;
play: () => void;
stop: () => void;
setSpeed: (speed: number) => void;
isTranslating: () => boolean;
handleTranslate: (callback: () => void) => void;
};
};
RybenaDOM?: {
getInstance: () => {
getRybenaScripts: (mode?: string) => void;
};
};
}
}
export default function RybenaComponent() {
const [isLoaded, setIsLoaded] = useState(false);
const [isTranslating, setIsTranslating] = useState(false);
const [text, setText] = useState('');
const [speed, setSpeed] = useState(1.0);
const [mode, setMode] = useState<'libras' | 'voz'>('libras');
useEffect(() => {
// Carrega o script Rybená
const script = document.createElement('script');
script.src = 'https://cdn.rybena.com.br/dom/master/latest/rybena.js?mode=api';
script.async = true;
script.onload = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().handleLoaded(() => {
setIsLoaded(true);
window.RybenaApi.getInstance().openPlayer();
window.RybenaApi.getInstance().switchToLibras();
});
}
};
document.head.appendChild(script);
return () => {
document.head.removeChild(script);
};
}, []);
const handleTranslate = () => {
if (text && window.RybenaApi) {
setIsTranslating(true);
window.RybenaApi.getInstance().translate(text);
}
};
const handlePause = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().pause();
}
};
const handlePlay = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().play();
}
};
const handleStop = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().stop();
setIsTranslating(false);
}
};
const handleSpeedChange = (newSpeed: number) => {
setSpeed(newSpeed);
if (window.RybenaApi) {
window.RybenaApi.getInstance().setSpeed(newSpeed);
}
};
const handleModeChange = (newMode: 'libras' | 'voz') => {
setMode(newMode);
if (window.RybenaApi) {
if (newMode === 'libras') {
window.RybenaApi.getInstance().switchToLibras();
} else {
window.RybenaApi.getInstance().switchToVoz();
}
}
};
if (!isLoaded) {
return <div>Carregando Rybená...</div>;
}
return (
<div className="rybena-container">
<h1>Rybená - React Integration</h1>
<div className="controls">
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Digite o texto para traduzir..."
rows={4}
/>
<div className="mode-selector">
<button
className={mode === 'libras' ? 'active' : ''}
onClick={() => handleModeChange('libras')}
>
LIBRAS
</button>
<button
className={mode === 'voz' ? 'active' : ''}
onClick={() => handleModeChange('voz')}
>
Voz
</button>
</div>
<div className="speed-selector">
<label>Velocidade:</label>
<button onClick={() => handleSpeedChange(0.75)}>Lento</button>
<button onClick={() => handleSpeedChange(1.0)}>Normal</button>
<button onClick={() => handleSpeedChange(1.5)}>Rápido</button>
</div>
<div className="playback-controls">
<button onClick={handleTranslate} disabled={!text}>
Traduzir
</button>
<button onClick={handlePause} disabled={!isTranslating}>
Pausar
</button>
<button onClick={handlePlay} disabled={!isTranslating}>
Continuar
</button>
<button onClick={handleStop} disabled={!isTranslating}>
Parar
</button>
</div>
</div>
</div>
);
}'use client';
import { useEffect, useState } from 'react';
declare global {
interface Window {
RybenaApi?: {
getInstance: () => {
handleLoaded: (callback: () => void) => void;
openPlayer: () => void;
closePlayer: () => void;
translate: (text: string) => void;
switchToLibras: () => void;
switchToVoz: () => void;
pause: () => void;
play: () => void;
stop: () => void;
setSpeed: (speed: number) => void;
isTranslating: () => boolean;
handleTranslate: (callback: () => void) => void;
};
};
}
}
export default function RybenaPage() {
const [isLoaded, setIsLoaded] = useState(false);
const [isTranslating, setIsTranslating] = useState(false);
const [text, setText] = useState('');
useEffect(() => {
// Carrega o script Rybená apenas no cliente
if (typeof window !== 'undefined') {
const script = document.createElement('script');
script.src = 'https://cdn.rybena.com.br/dom/master/latest/rybena.js?mode=api';
script.async = true;
script.onload = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().handleLoaded(() => {
setIsLoaded(true);
window.RybenaApi.getInstance().openPlayer();
window.RybenaApi.getInstance().switchToLibras();
});
}
};
document.head.appendChild(script);
return () => {
if (document.head.contains(script)) {
document.head.removeChild(script);
}
};
}
}, []);
const handleTranslate = () => {
if (text && window.RybenaApi) {
setIsTranslating(true);
window.RybenaApi.getInstance().translate(text);
// Configura callback para quando a tradução terminar
window.RybenaApi.getInstance().handleTranslate(() => {
setIsTranslating(false);
});
}
};
if (!isLoaded) {
return (
<div className="flex items-center justify-center min-h-screen">
<p>Carregando Rybená...</p>
</div>
);
}
return (
<div className="container mx-auto p-4">
<h1 className="text-3xl font-bold mb-6">Rybená - Next.js Integration</h1>
<div className="bg-white rounded-lg shadow-md p-6">
<textarea
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Digite o texto para traduzir..."
className="w-full p-3 border rounded-lg mb-4"
rows={4}
/>
<div className="flex gap-2">
<button
onClick={handleTranslate}
disabled={!text}
className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600 disabled:opacity-50"
>
Traduzir em LIBRAS
</button>
<button
onClick={() => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().pause();
}
}}
disabled={!isTranslating}
className="bg-yellow-500 text-white px-4 py-2 rounded hover:bg-yellow-600 disabled:opacity-50"
>
Pausar
</button>
<button
onClick={() => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().play();
}
}}
disabled={!isTranslating}
className="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600 disabled:opacity-50"
>
Continuar
</button>
<button
onClick={() => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().stop();
setIsTranslating(false);
}
}}
disabled={!isTranslating}
className="bg-red-500 text-white px-4 py-2 rounded hover:bg-red-600 disabled:opacity-50"
>
Parar
</button>
</div>
{isTranslating && (
<p className="mt-4 text-blue-600">Traduzindo...</p>
)}
</div>
</div>
);
}<template>
<div class="rybena-container">
<h1>Rybená - Vue Integration</h1>
<div v-if="!isLoaded" class="loading">
Carregando Rybená...
</div>
<div v-else class="controls">
<textarea
v-model="text"
placeholder="Digite o texto para traduzir..."
rows="4"
/>
<div class="mode-selector">
<button
:class="{ active: mode === 'libras' }"
@click="setMode('libras')"
>
LIBRAS
</button>
<button
:class="{ active: mode === 'voz' }"
@click="setMode('voz')"
>
Voz
</button>
</div>
<div class="speed-selector">
<label>Velocidade:</label>
<button @click="setSpeed(0.75)">Lento</button>
<button @click="setSpeed(1.0)">Normal</button>
<button @click="setSpeed(1.5)">Rápido</button>
</div>
<div class="playback-controls">
<button @click="translate" :disabled="!text">
Traduzir
</button>
<button @click="pause" :disabled="!isTranslating">
Pausar
</button>
<button @click="play" :disabled="!isTranslating">
Continuar
</button>
<button @click="stop" :disabled="!isTranslating">
Parar
</button>
</div>
<p v-if="isTranslating" class="status">
Traduzindo...
</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
declare global {
interface Window {
RybenaApi?: {
getInstance: () => {
handleLoaded: (callback: () => void) => void;
openPlayer: () => void;
closePlayer: () => void;
translate: (text: string) => void;
switchToLibras: () => void;
switchToVoz: () => void;
pause: () => void;
play: () => void;
stop: () => void;
setSpeed: (speed: number) => void;
isTranslating: () => boolean;
handleTranslate: (callback: () => void) => void;
};
};
}
const isLoaded = ref(false);
const isTranslating = ref(false);
const text = ref('');
const speed = ref(1.0);
const mode = ref<'libras' | 'voz'>('libras');
onMounted(() => {
const script = document.createElement('script');
script.src = 'https://cdn.rybena.com.br/dom/master/latest/rybena.js?mode=api';
script.async = true;
script.onload = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().handleLoaded(() => {
isLoaded.value = true;
window.RybenaApi.getInstance().openPlayer();
window.RybenaApi.getInstance().switchToLibras();
});
}
};
document.head.appendChild(script);
});
const translate = () => {
if (text.value && window.RybenaApi) {
isTranslating.value = true;
window.RybenaApi.getInstance().translate(text.value);
window.RybenaApi.getInstance().handleTranslate(() => {
isTranslating.value = false;
});
}
};
const pause = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().pause();
}
};
const play = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().play();
}
};
const stop = () => {
if (window.RybenaApi) {
window.RybenaApi.getInstance().stop();
isTranslating.value = false;
}
};
const setSpeed = (newSpeed: number) => {
speed.value = newSpeed;
if (window.RybenaApi) {
window.RybenaApi.getInstance().setSpeed(newSpeed);
}
};
const setMode = (newMode: 'libras' | 'voz') => {
mode.value = newMode;
if (window.RybenaApi) {
if (newMode === 'libras') {
window.RybenaApi.getInstance().switchToLibras();
} else {
window.RybenaApi.getInstance().switchToVoz();
}
}
};
</script>
<style scoped>
.rybena-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.loading {
text-align: center;
padding: 40px;
}
.controls {
display: flex;
flex-direction: column;
gap: 20px;
}
textarea {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
}
.mode-selector,
.speed-selector,
.playback-controls {
display: flex;
gap: 10px;
align-items: center;
}
button {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
background-color: #007bff;
color: white;
font-size: 14px;
}
button:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
button.active {
background-color: #0056b3;
}
.status {
color: #007bff;
font-weight: bold;
}
</style><!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rybená - Vanilla JavaScript</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
textarea {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
margin-bottom: 15px;
}
.controls {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 15px;
}
button {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
background-color: #007bff;
color: white;
font-size: 14px;
}
button:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
button.active {
background-color: #0056b3;
}
.status {
padding: 10px;
border-radius: 4px;
margin-top: 15px;
}
.status.translating {
background-color: #d4edda;
color: #155724;
}
.status.ready {
background-color: #d1ecf1;
color: #0c5460;
}
</style>
</head>
<body>
<div class="container">
<h1>Rybená - Vanilla JavaScript</h1>
<div id="loading" style="display: none;">
<p>Carregando Rybená...</p>
</div>
<div id="controls" style="display: none;">
<textarea
id="textInput"
placeholder="Digite o texto para traduzir..."
rows="4"
></textarea>
<div class="controls">
<button id="librasBtn" class="active">LIBRAS</button>
<button id="vozBtn">Voz</button>
</div>
<div class="controls">
<button id="slowBtn">Lento</button>
<button id="normalBtn" class="active">Normal</button>
<button id="fastBtn">Rápido</button>
</div>
<div class="controls">
<button id="translateBtn">Traduzir</button>
<button id="pauseBtn" disabled>Pausar</button>
<button id="playBtn" disabled>Continuar</button>
<button id="stopBtn" disabled>Parar</button>
</div>
<div id="status" class="status ready">
Pronto para traduzir
</div>
</div>
</div>
<script type="text/javascript" src="https://cdn.rybena.com.br/dom/master/latest/rybena.js?mode=api"></script>
<script>
// Elementos DOM
const loading = document.getElementById('loading');
const controls = document.getElementById('controls');
const textInput = document.getElementById('textInput');
const status = document.getElementById('status');
const librasBtn = document.getElementById('librasBtn');
const vozBtn = document.getElementById('vozBtn');
const slowBtn = document.getElementById('slowBtn');
const normalBtn = document.getElementById('normalBtn');
const fastBtn = document.getElementById('fastBtn');
const translateBtn = document.getElementById('translateBtn');
const pauseBtn = document.getElementById('pauseBtn');
const playBtn = document.getElementById('playBtn');
const stopBtn = document.getElementById('stopBtn');
let currentMode = 'libras';
let currentSpeed = 1.0;
// Aguarda a Rybená carregar
RybenaApi.getInstance().handleLoaded(() => {
console.log('Rybená carregada!');
// Mostra os controles
loading.style.display = 'none';
controls.style.display = 'block';
// Abre o player
RybenaApi.getInstance().openPlayer();
RybenaApi.getInstance().switchToLibras();
});
// Configura callback para quando a tradução terminar
RybenaApi.getInstance().handleTranslate(() => {
console.log('Tradução concluída!');
updateStatus('ready', 'Pronto para traduzir');
updateButtonStates();
});
// Funções de controle
function translate() {
const text = textInput.value.trim();
if (text) {
updateStatus('translating', 'Traduzindo...');
RybenaApi.getInstance().translate(text);
updateButtonStates();
}
}
function pause() {
RybenaApi.getInstance().pause();
updateStatus('ready', 'Tradução pausada');
}
function play() {
RybenaApi.getInstance().play();
updateStatus('translating', 'Traduzindo...');
}
function stop() {
RybenaApi.getInstance().stop();
updateStatus('ready', 'Tradução parada');
updateButtonStates();
}
function setMode(mode) {
currentMode = mode;
if (mode === 'libras') {
RybenaApi.getInstance().switchToLibras();
librasBtn.classList.add('active');
vozBtn.classList.remove('active');
} else {
RybenaApi.getInstance().switchToVoz();
vozBtn.classList.add('active');
librasBtn.classList.remove('active');
}
}
function setSpeed(speed) {
currentSpeed = speed;
RybenaApi.getInstance().setSpeed(speed);
slowBtn.classList.remove('active');
normalBtn.classList.remove('active');
fastBtn.classList.remove('active');
if (speed === 0.75) {
slowBtn.classList.add('active');
} else if (speed === 1.0) {
normalBtn.classList.add('active');
} else if (speed === 1.5) {
fastBtn.classList.add('active');
}
}
function updateStatus(type, message) {
status.className = 'status ' + type;
status.textContent = message;
}
function updateButtonStates() {
const isTranslating = RybenaApi.getInstance().isTranslating();
const hasText = textInput.value.trim().length > 0;
translateBtn.disabled = !hasText || isTranslating;
pauseBtn.disabled = !isTranslating;
playBtn.disabled = !isTranslating;
stopBtn.disabled = !isTranslating;
}
// Event listeners
translateBtn.addEventListener('click', translate);
pauseBtn.addEventListener('click', pause);
playBtn.addEventListener('click', play);
stopBtn.addEventListener('click', stop);
librasBtn.addEventListener('click', () => setMode('libras'));
vozBtn.addEventListener('click', () => setMode('voz'));
slowBtn.addEventListener('click', () => setSpeed(0.75));
normalBtn.addEventListener('click', () => setSpeed(1.0));
fastBtn.addEventListener('click', () => setSpeed(1.5));
textInput.addEventListener('input', updateButtonStates);
</script>
</body>
</html>Casos de Uso Comuns
Caso de Uso 1: Tradução de Conteúdo Dinâmico
Este exemplo mostra como traduzir conteúdo que é carregado dinamicamente:
RybenaApi.getInstance().handleLoaded(() => {
RybenaApi.getInstance().openPlayer();
RybenaApi.getInstance().switchToLibras();
// Função para traduzir conteúdo dinâmico
function translateDynamicContent() {
const contentElement = document.getElementById('dynamic-content');
const text = contentElement.textContent;
if (text) {
RybenaApi.getInstance().translate(text);
}
}
// Simula carregamento de conteúdo dinâmico
setTimeout(() => {
document.getElementById('dynamic-content').textContent =
'Este conteúdo foi carregado dinamicamente e será traduzido automaticamente.';
translateDynamicContent();
}, 2000);
});Caso de Uso 2: Integração com Vídeo
Este exemplo mostra como sincronizar a tradução com um vídeo:
RybenaApi.getInstance().handleLoaded(() => {
RybenaApi.getInstance().openPlayer();
RybenaApi.getInstance().switchToLibras();
const video = document.getElementById('myVideo');
const subtitles = [
{ start: 0, end: 5, text: 'Bem-vindo ao nosso vídeo' },
{ start: 5, end: 10, text: 'Hoje vamos aprender sobre acessibilidade' },
{ start: 10, end: 15, text: 'A Rybená ajuda a tornar o conteúdo acessível' }
];
let currentSubtitleIndex = 0;
// Função para traduzir a legenda atual
function translateCurrentSubtitle() {
const currentTime = video.currentTime;
const currentSubtitle = subtitles.find(
sub => currentTime >= sub.start && currentTime < sub.end
);
if (currentSubtitle) {
RybenaApi.getInstance().translate(currentSubtitle.text);
}
}
// Atualiza a tradução quando o tempo do vídeo muda
video.addEventListener('timeupdate', () => {
const currentTime = video.currentTime;
const newIndex = subtitles.findIndex(
sub => currentTime >= sub.start && currentTime < sub.end
);
if (newIndex !== -1 && newIndex !== currentSubtitleIndex) {
currentSubtitleIndex = newIndex;
translateCurrentSubtitle();
}
});
// Pausa a tradução quando o vídeo é pausado
video.addEventListener('pause', () => {
RybenaApi.getInstance().pause();
});
// Retoma a tradução quando o vídeo é reproduzido
video.addEventListener('play', () => {
RybenaApi.getInstance().play();
});
});Caso de Uso 3: Tradução de Formulários
Este exemplo mostra como traduzir mensagens de erro e validação de formulários:
RybenaApi.getInstance().handleLoaded(() => {
RybenaApi.getInstance().openPlayer();
RybenaApi.getInstance().switchToVoz();
const form = document.getElementById('myForm');
const nameInput = document.getElementById('name');
const emailInput = document.getElementById('email');
// Função para traduzir mensagens de erro
function translateErrorMessage(message) {
RybenaApi.getInstance().translate(message);
}
// Validação do formulário
form.addEventListener('submit', (e) => {
e.preventDefault();
const name = nameInput.value.trim();
const email = emailInput.value.trim();
if (!name) {
translateErrorMessage('Por favor, preencha o campo nome.');
return;
}
if (!email) {
translateErrorMessage('Por favor, preencha o campo e-mail.');
return;
}
if (!email.includes('@')) {
translateErrorMessage('Por favor, insira um e-mail válido.');
return;
}
translateErrorMessage('Formulário enviado com sucesso!');
});
// Traduz rótulos dos campos quando focados
nameInput.addEventListener('focus', () => {
RybenaApi.getInstance().translate('Campo nome: digite seu nome completo.');
});
emailInput.addEventListener('focus', () => {
RybenaApi.getInstance().translate('Campo e-mail: digite seu endereço de e-mail.');
});
});Caso de Uso 4: Tradução de Notificações
Este exemplo mostra como traduzir notificações do sistema:
RybenaApi.getInstance().handleLoaded(() => {
RybenaApi.getInstance().openPlayer();
RybenaApi.getInstance().switchToVoz();
// Função para mostrar e traduzir notificações
function showNotification(message, type = 'info') {
// Cria elemento de notificação
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.textContent = message;
document.body.appendChild(notification);
// Traduz a mensagem
RybenaApi.getInstance().translate(message);
// Remove a notificação após 5 segundos
setTimeout(() => {
document.body.removeChild(notification);
}, 5000);
}
// Exemplos de uso
document.getElementById('successBtn').addEventListener('click', () => {
showNotification('Operação realizada com sucesso!', 'success');
});
document.getElementById('errorBtn').addEventListener('click', () => {
showNotification('Ocorreu um erro. Tente novamente.', 'error');
});
document.getElementById('warningBtn').addEventListener('click', () => {
showNotification('Atenção: verifique os dados informados.', 'warning');
});
});Caso de Uso 5: Tradução de Conteúdo de Acessibilidade
Este exemplo mostra como traduzir descrições de elementos de acessibilidade:
RybenaApi.getInstance().handleLoaded(() => {
RybenaApi.getInstance().openPlayer();
RybenaApi.getInstance().switchToVoz();
// Traduz descrições de imagens quando focadas
const images = document.querySelectorAll('img[alt]');
images.forEach(img => {
img.addEventListener('focus', () => {
const altText = img.getAttribute('alt');
if (altText) {
RybenaApi.getInstance().translate(`Imagem: ${altText}`);
}
});
});
// Traduz descrições de links quando focados
const links = document.querySelectorAll('a[aria-label]');
links.forEach(link => {
link.addEventListener('focus', () => {
const ariaLabel = link.getAttribute('aria-label');
if (ariaLabel) {
RybenaApi.getInstance().translate(`Link: ${ariaLabel}`);
}
});
});
// Traduz descrições de botões quando focados
const buttons = document.querySelectorAll('button[aria-label]');
buttons.forEach(button => {
button.addEventListener('focus', () => {
const ariaLabel = button.getAttribute('aria-label');
if (ariaLabel) {
RybenaApi.getInstance().translate(`Botão: ${ariaLabel}`);
}
});
});
});Boas Práticas
Dica: Sempre use handleLoaded() antes de fazer qualquer chamada à API para garantir que o script foi completamente carregado.
Atenção: Em frameworks como Next.js, certifique-se de carregar o script apenas no cliente usando 'use client' ou verificações de typeof window !== 'undefined'.
Sugestão: Salve as preferências do usuário (velocidade, modo de tradução, etc.) em localStorage para persistir entre sessões.
Dica: Use handleTranslate() para executar ações após a tradução ser concluída, como atualizar a interface ou traduzir o próximo texto.
Conteúdo Relacionado
Recursos de Acessibilidade
A API Rybená oferece uma ampla gama de recursos de acessibilidade para melhorar a experiência de usuários com diferentes necessidades. Os recursos estão organizados em categorias para facilitar o uso.
Suporte TypeScript
A API Rybená oferece suporte completo a TypeScript, permitindo que você aproveite os benefícios de tipagem estática, autocompletar e verificação de erros em tempo de compilação.