Rybená Logo

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

Nesta página