Commit 85e7af4e authored by Erik Nordin's avatar Erik Nordin Committed by enordin@mozilla.com
Browse files

Bug 1820252 - Lazify Full-Page Translations r=translations-reviewers,gregtatum

This patch introduces IntersectionObservers into the
TranslationsDocument, rewriting the algorithm to allow
translating only node content and attributes that are
within close proximity to the device's viewport.

Differential Revision: https://phabricator.services.mozilla.com/D249983
parent 3facdb37
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ export class TranslationsChild extends JSWindowActorChild {

    switch (name) {
      case "Translations:TranslatePage": {
        if (this.#translatedDoc?.translator.engineStatus === "error") {
        if (this.#translatedDoc?.engineStatus === "error") {
          this.#translatedDoc.destroy();
          this.#translatedDoc = null;
        }
@@ -145,7 +145,7 @@ export class TranslationsChild extends JSWindowActorChild {
      }
      case "Translations:AcquirePort": {
        this.addProfilerMarker("Acquired a port, resuming translations");
        this.#translatedDoc.translator.acquirePort(data.port);
        this.#translatedDoc.acquirePort(data.port);
        return undefined;
      }
      default:
+3027 −610

File changed.

Preview size limit exceeded, changes collapsed.

+54 −0
Original line number Diff line number Diff line
@@ -614,23 +614,66 @@ function listenForPortMessages(languagePair, innerWindowId, port) {
        );
        break;
      }
      case "TranslationsPort:Passthrough": {
        const { translationId } = data;

        port.postMessage({
          type: "TranslationsPort:TranslationResponse",
          translationId,
          targetText: null,
        });

        TE_addProfilerMarker({
          innerWindowId,
          type: "Passthrough",
          message: `Handled passthrough translation`,
        });

        break;
      }
      case "TranslationsPort:CachedTranslation": {
        const { cachedTranslation, translationId } = data;
        port.postMessage({
          type: "TranslationsPort:TranslationResponse",
          translationId,
          targetText: cachedTranslation,
        });

        TE_addProfilerMarker({
          innerWindowId,
          type: "Cached",
          message: `Handled cached translation of ${cachedTranslation.length} code units`,
        });

        break;
      }
      case "TranslationsPort:TranslationRequest": {
        const { sourceText, isHTML, translationId } = data;

        const engine = await TranslationsEngine.getOrCreate(
          languagePair,
          innerWindowId
        );

        TE_addProfilerMarker({
          innerWindowId,
          type: "Request",
          message: `Handled translation request of ${sourceText.length} code units`,
        });

        const targetText = await engine.translate(
          sourceText,
          isHTML,
          innerWindowId,
          translationId
        );

        port.postMessage({
          type: "TranslationsPort:TranslationResponse",
          translationId,
          targetText,
        });

        break;
      }
      case "TranslationsPort:CancelSingleTranslation": {
@@ -638,10 +681,21 @@ function listenForPortMessages(languagePair, innerWindowId, port) {
        TranslationsEngine.withCachedEngine(languagePair, engine => {
          engine.cancelSingleTranslation(innerWindowId, translationId);
        });

        TE_addProfilerMarker({
          innerWindowId,
          type: "Cancel",
          message: `Cancelled request for translationId ${translationId}`,
        });
        break;
      }
      case "TranslationsPort:DiscardTranslations": {
        discardTranslations(innerWindowId);
        TE_addProfilerMarker({
          innerWindowId,
          type: "Discard",
          message: `Discarded all active translation requests`,
        });
        break;
      }
      default:
+19 −8
Original line number Diff line number Diff line
@@ -256,7 +256,7 @@ interface TranslationsEnginePayload {
/**
 * Nodes that are being translated are given priority according to their visibility.
 */
export type NodeVisibility = "in-viewport" | "out-of-viewport" | "hidden";
export type NodeVisibility = "in-viewport" | "beyond-viewport" | "hidden";

/**
 * Used to decide how to translate a page for full page translations.
@@ -383,7 +383,17 @@ export type RequestTranslationsPort = (
  languagePair: LanguagePair
) => Promise<MessagePort>;

export type TranslationsPortMessages = {
export type TranslationsPortMessages =
  // We have determined that the source text is already translated into the target language, so do nothing.
  | { type: "TranslationsPort:Passthrough"; translationId: string }
  // We found translated text for this request in our cache, so send the targetText directly without translating.
  | {
      type: "TranslationsPort:CachedTranslation";
      translationId: string;
      targetText: string;
    }
  // This is a new, uncached request, and it needs to be translated by the TranslationsEngine.
  | {
      type: "TranslationsPort:TranslationRequest";
      translationId: string;
      sourceText: string;
@@ -393,9 +403,10 @@ export type TranslationsPortMessages = {
export type EngineStatus = "uninitialized" | "ready" | "error" | "closed";

export type PortToPage =
  // The targetText may be null if the TranslationsEngine had an error, or if this is a response to a Passthrough.
  | {
      type: "TranslationsPort:TranslationResponse";
      targetText: string;
      targetText: string | null;
      translationId: number;
    }
  | { type: "TranslationsPort:GetEngineStatusResponse"; status: EngineStatus }