Integrar LibreTranslate para traducao automatica
This commit is contained in:
134
frontend/src/components/TranslatedText.tsx
Normal file
134
frontend/src/components/TranslatedText.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState, ElementType, ComponentPropsWithoutRef } from 'react';
|
||||
import { useTranslate } from '@/hooks/useTranslate';
|
||||
|
||||
interface TranslatedTextProps {
|
||||
text: string;
|
||||
as?: 'span' | 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div' | 'li';
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Componente que traduz texto automaticamente via LibreTranslate
|
||||
* quando o idioma não é português
|
||||
*/
|
||||
export function TranslatedText({ text, as = 'span', className }: TranslatedTextProps) {
|
||||
const { translate, language } = useTranslate();
|
||||
const [translatedText, setTranslatedText] = useState(text);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (language === 'PT') {
|
||||
setTranslatedText(text);
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
setIsLoading(true);
|
||||
|
||||
translate(text).then((result) => {
|
||||
if (!cancelled) {
|
||||
setTranslatedText(result);
|
||||
setIsLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [text, language, translate]);
|
||||
|
||||
const Tag = as;
|
||||
|
||||
return (
|
||||
<Tag className={className} data-translating={isLoading}>
|
||||
{translatedText}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook para traduzir objetos de conteúdo do banco de dados
|
||||
*/
|
||||
export function useTranslatedContent<T extends Record<string, unknown>>(content: T): {
|
||||
translatedContent: T;
|
||||
isTranslating: boolean
|
||||
} {
|
||||
const { translateBatch, language } = useTranslate();
|
||||
const [translatedContent, setTranslatedContent] = useState<T>(content);
|
||||
const [isTranslating, setIsTranslating] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (language === 'PT') {
|
||||
setTranslatedContent(content);
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
|
||||
const translateContent = async () => {
|
||||
setIsTranslating(true);
|
||||
|
||||
// Extrair todos os textos do objeto
|
||||
const texts: string[] = [];
|
||||
const paths: string[] = [];
|
||||
|
||||
const extractTexts = (obj: unknown, path: string = '') => {
|
||||
if (typeof obj === 'string' && obj.length > 0) {
|
||||
texts.push(obj);
|
||||
paths.push(path);
|
||||
} else if (Array.isArray(obj)) {
|
||||
obj.forEach((item, index) => extractTexts(item, `${path}[${index}]`));
|
||||
} else if (obj && typeof obj === 'object') {
|
||||
Object.entries(obj).forEach(([key, value]) => {
|
||||
extractTexts(value, path ? `${path}.${key}` : key);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
extractTexts(content);
|
||||
|
||||
if (texts.length === 0) {
|
||||
setIsTranslating(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const translations = await translateBatch(texts);
|
||||
|
||||
if (cancelled) return;
|
||||
|
||||
// Reconstruir objeto com traduções
|
||||
const newContent = JSON.parse(JSON.stringify(content));
|
||||
|
||||
paths.forEach((path, index) => {
|
||||
const parts = path.replace(/\[(\d+)\]/g, '.$1').split('.');
|
||||
let current: Record<string, unknown> = newContent;
|
||||
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
current = current[parts[i]] as Record<string, unknown>;
|
||||
}
|
||||
|
||||
current[parts[parts.length - 1]] = translations[index];
|
||||
});
|
||||
|
||||
setTranslatedContent(newContent);
|
||||
} catch (error) {
|
||||
console.error('Translation error:', error);
|
||||
} finally {
|
||||
if (!cancelled) {
|
||||
setIsTranslating(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
translateContent();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [content, language, translateBatch]);
|
||||
|
||||
return { translatedContent, isTranslating };
|
||||
}
|
||||
Reference in New Issue
Block a user