translator: lazy load translation observer (#1282)

This commit is contained in:
Huang Xin
2025-05-30 15:08:45 +08:00
committed by GitHub
parent 6c86917098
commit c7a583c53a
4 changed files with 25 additions and 21 deletions
@@ -9,11 +9,11 @@ import { getLocale } from '@/utils/misc';
export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElement | null) {
const { getViewSettings } = useReaderStore();
const viewSettings = getViewSettings(bookKey)!;
const viewSettings = getViewSettings(bookKey);
const enabled = useRef(viewSettings.translationEnabled);
const [provider, setProvider] = useState(viewSettings.translationProvider);
const [targetLang, setTargetLang] = useState(viewSettings.translateTargetLang);
const enabled = useRef(viewSettings?.translationEnabled);
const [provider, setProvider] = useState(viewSettings?.translationProvider);
const [targetLang, setTargetLang] = useState(viewSettings?.translateTargetLang);
const { translate } = useTranslator({
provider,
@@ -42,6 +42,16 @@ export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElem
translateRef.current = translate;
}, [translate]);
const observeTextNodes = () => {
if (!view || !enabled.current) return;
const observer = createTranslationObserver();
observerRef.current = observer;
const nodes = walkTextNodes(view);
console.log('Observing text nodes for translation:', nodes.length);
allTextNodes.current = nodes;
nodes.forEach((el) => observer.observe(el));
};
const updateTranslation = () => {
translatedElements.current.forEach((element) => {
const translationTargets = element.querySelectorAll('.translation-target');
@@ -49,7 +59,7 @@ export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElem
});
translatedElements.current = [];
if (viewSettings.translationEnabled && view) {
if (viewSettings?.translationEnabled && view) {
recreateTranslationObserver();
}
};
@@ -168,7 +178,7 @@ export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElem
if (enabledChanged) {
toggleTranslationVisibility(viewSettings.translationEnabled);
if (enabled.current) {
recreateTranslationObserver();
observeTextNodes();
}
} else if (providerChanged || targetLangChanged) {
updateTranslation();
@@ -177,15 +187,7 @@ export function useTextTranslation(bookKey: string, view: FoliateView | HTMLElem
}, [bookKey, viewSettings, provider, targetLang]);
useEffect(() => {
if (!view) return;
const observeTextNodes = () => {
const observer = createTranslationObserver();
observerRef.current = observer;
const nodes = walkTextNodes(view);
allTextNodes.current = nodes;
nodes.forEach((el) => observer.observe(el));
};
if (!view || !enabled.current) return;
if ('renderer' in view) {
view.addEventListener('load', observeTextNodes);
+1 -1
View File
@@ -401,7 +401,7 @@ export abstract class BaseAppService implements AppService {
}
} catch (error) {
// don't throw error here since some books may not have cover images at all
console.log('Failed to download cover file:', error);
console.log(`Failed to download cover file for book: '${book.title}'`, error);
}
if (needDownBook) {
@@ -86,6 +86,7 @@ export class TTSController extends EventTarget {
.replace(/[–—]/g, ',')
.replace('<break/>', ' ')
.replace(/\.{3,}/g, ' ')
.replace(/……/g, ' ')
.replace(/·/g, ' ');
return ssml;
+6 -5
View File
@@ -59,7 +59,7 @@ export const updateToc = (bookDoc: BookDoc, items: TOCItem[], sections: SectionI
map[section.id] = section;
return map;
}, {});
updateTocData(bookDoc, items, sectionsMap);
updateTocData(bookDoc, items, sections, sectionsMap);
items.sort((a, b) => {
if (a.location && b.location) {
return a.location.current - b.location.current;
@@ -71,25 +71,26 @@ export const updateToc = (bookDoc: BookDoc, items: TOCItem[], sections: SectionI
const updateTocData = (
bookDoc: BookDoc,
items: TOCItem[],
sections: { [id: string]: SectionItem },
sections: SectionItem[],
sectionsMap: { [id: string]: SectionItem },
index = 0,
): number => {
items.forEach((item) => {
item.id ??= index++;
if (item.href) {
const id = bookDoc.splitTOCHref(item.href)[0]!;
const section = sections[id];
const section = sectionsMap[id];
if (section) {
item.cfi = section.cfi;
// Add location only when toc item is at the same level as the section
// otherwise the location will not be accurate
if (id === item.href) {
if (id === item.href || items.length <= sections.length) {
item.location = section.location;
}
}
}
if (item.subitems) {
index = updateTocData(bookDoc, item.subitems, sections, index);
index = updateTocData(bookDoc, item.subitems, sections, sectionsMap, index);
}
});
return index;