[api-minor] Use "data-l10n-id"/"data-l10n-args", rather than manually updating DOM-elements, to trigger translation (PR 17146 follow-up)

This patch changes almost all viewer-components[1] to use "data-l10n-id"/"data-l10n-args" for localization, which means that in many cases we no longer need to pass around the `L10n`-instance any more.

One part of the code-base where the `L10n`-instance is still being used "directly" is the AnnotationEditors, however while it might be possible to convert (most of) that code as well that's not attempted in this patch.

---
[1] The one exception is the `PDFDocumentProperties` dialog, since the way it's currently implemented makes that less straightforward to fix without a lot of code changes.
This commit is contained in:
Jonas Jenwald 2023-10-19 16:30:57 +02:00
parent 898cc2e399
commit 17af706070
17 changed files with 117 additions and 149 deletions

View File

@ -218,11 +218,13 @@ pdfjs-additional-layers = Additional Layers
# Variables:
# $page (Number) - the page number
pdfjs-thumb-page-title = Page { $page }
pdfjs-thumb-page-title =
.title = Page { $page }
# Variables:
# $page (Number) - the page number
pdfjs-thumb-page-canvas = Thumbnail of Page { $page }
pdfjs-thumb-page-canvas =
.aria-label = Thumbnail of Page { $page }
## Find panel button title and messages
@ -276,7 +278,8 @@ pdfjs-page-scale-percent = { $scale }%
# Variables:
# $page (Number) - the page number
pdfjs-page-landmark = Page { $page }
pdfjs-page-landmark =
.aria-label = Page { $page }
## Loading indicator messages

View File

@ -983,8 +983,11 @@ class TextAnnotationElement extends AnnotationElement {
"annotation-" +
this.data.name.toLowerCase() +
".svg";
image.dataset.l10nId = "pdfjs-text-annotation-type";
image.dataset.l10nArgs = JSON.stringify({ type: this.data.name });
image.setAttribute("data-l10n-id", "pdfjs-text-annotation-type");
image.setAttribute(
"data-l10n-args",
JSON.stringify({ type: this.data.name })
);
if (!this.data.popupRef && this.hasPopupData) {
this._createPopup();
@ -2158,11 +2161,17 @@ class PopupElement {
if (this.#dateObj) {
const modificationDate = document.createElement("span");
modificationDate.classList.add("popupDate");
modificationDate.dataset.l10nId = "pdfjs-annotation-date-string";
modificationDate.dataset.l10nArgs = JSON.stringify({
modificationDate.setAttribute(
"data-l10n-id",
"pdfjs-annotation-date-string"
);
modificationDate.setAttribute(
"data-l10n-args",
JSON.stringify({
date: this.#dateObj.toLocaleDateString(),
time: this.#dateObj.toLocaleTimeString(),
});
})
);
header.append(modificationDate);
}
@ -2889,14 +2898,12 @@ class AnnotationLayer {
div,
accessibilityManager,
annotationCanvasMap,
l10n,
page,
viewport,
}) {
this.div = div;
this.#accessibilityManager = accessibilityManager;
this.#annotationCanvasMap = annotationCanvasMap;
this.l10n = l10n;
this.page = page;
this.viewport = viewport;
this.zIndex = 0;

View File

@ -25,8 +25,7 @@ const {
shadow,
XfaLayer,
} = pdfjsLib;
const { GenericL10n, NullL10n, parseQueryString, SimpleLinkService } =
pdfjsViewer;
const { GenericL10n, parseQueryString, SimpleLinkService } = pdfjsViewer;
const WAITING_TIME = 100; // ms
const CMAP_URL = "/build/generic/web/cmaps/";
@ -215,8 +214,7 @@ class Rasterize {
annotationCanvasMap,
page,
imageResourcesPath,
renderForms = false,
l10n = NullL10n
renderForms = false
) {
try {
const { svg, foreignObject, style, div } = this.createContainer(viewport);
@ -248,7 +246,6 @@ class Rasterize {
div,
annotationCanvasMap: annotationImageMap,
page,
l10n,
viewport: annotationViewport,
});
await annotationLayer.render(parameters);
@ -356,6 +353,8 @@ class Driver {
// Configure the global worker options.
GlobalWorkerOptions.workerSrc = WORKER_SRC;
// We only need to initialize the `L10n`-instance here, since translation is
// triggered by a `MutationObserver`; see e.g. `Rasterize.annotationLayer`.
this._l10n = new GenericL10n(VIEWER_LOCALE);
// Set the passed options
@ -879,8 +878,7 @@ class Driver {
annotationCanvasMap,
page,
IMAGE_RESOURCES_PATH,
renderForms,
this._l10n
renderForms
).then(() => {
completeRender(false);
});

View File

@ -19,13 +19,11 @@
// eslint-disable-next-line max-len
/** @typedef {import("../src/display/annotation_storage").AnnotationStorage} AnnotationStorage */
/** @typedef {import("./interfaces").IDownloadManager} IDownloadManager */
/** @typedef {import("./interfaces").IL10n} IL10n */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
// eslint-disable-next-line max-len
/** @typedef {import("./text_accessibility.js").TextAccessibilityManager} TextAccessibilityManager */
import { AnnotationLayer } from "pdfjs-lib";
import { NullL10n } from "web-l10n_utils";
import { PresentationModeState } from "./ui_utils.js";
/**
@ -38,7 +36,6 @@ import { PresentationModeState } from "./ui_utils.js";
* @property {boolean} renderForms
* @property {IPDFLinkService} linkService
* @property {IDownloadManager} [downloadManager]
* @property {IL10n} l10n - Localization service.
* @property {boolean} [enableScripting]
* @property {Promise<boolean>} [hasJSActionsPromise]
* @property {Promise<Object<string, Array<Object>> | null>}
@ -61,7 +58,6 @@ class AnnotationLayerBuilder {
annotationStorage = null,
imageResourcesPath = "",
renderForms = true,
l10n = NullL10n,
enableScripting = false,
hasJSActionsPromise = null,
fieldObjectsPromise = null,
@ -74,7 +70,6 @@ class AnnotationLayerBuilder {
this.downloadManager = downloadManager;
this.imageResourcesPath = imageResourcesPath;
this.renderForms = renderForms;
this.l10n = l10n;
this.annotationStorage = annotationStorage;
this.enableScripting = enableScripting;
this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
@ -131,7 +126,6 @@ class AnnotationLayerBuilder {
div,
accessibilityManager: this._accessibilityManager,
annotationCanvasMap: this._annotationCanvasMap,
l10n: this.l10n,
page: this.pdfPage,
viewport: viewport.clone({ dontFlip: true }),
});

View File

@ -521,7 +521,6 @@ const PDFViewerApplication = {
eventBus,
renderingQueue: pdfRenderingQueue,
linkService: pdfLinkService,
l10n,
pageColors,
});
pdfRenderingQueue.setThumbnailViewer(this.pdfThumbnailViewer);
@ -538,7 +537,7 @@ const PDFViewerApplication = {
}
if (!this.supportsIntegratedFind && appConfig.findBar) {
this.findBar = new PDFFindBar(appConfig.findBar, eventBus, l10n);
this.findBar = new PDFFindBar(appConfig.findBar, eventBus);
}
if (appConfig.annotationEditorParams) {
@ -587,11 +586,10 @@ const PDFViewerApplication = {
this.toolbar = new Toolbar(
appConfig.toolbar,
eventBus,
l10n,
await this._nimbusDataPromise
);
} else {
this.toolbar = new Toolbar(appConfig.toolbar, eventBus, l10n);
this.toolbar = new Toolbar(appConfig.toolbar, eventBus);
}
}
@ -617,7 +615,6 @@ const PDFViewerApplication = {
this.passwordPrompt = new PasswordPrompt(
appConfig.passwordOverlay,
this.overlayManager,
l10n,
this.isViewerEmbedded
);
}
@ -643,7 +640,6 @@ const PDFViewerApplication = {
this.pdfLayerViewer = new PDFLayerViewer({
container: appConfig.sidebar.layersView,
eventBus,
l10n,
});
}
@ -1848,8 +1844,7 @@ const PDFViewerApplication = {
printContainer,
printResolution,
optionalContentConfigPromise,
this._printAnnotationStoragePromise,
this.l10n
this._printAnnotationStoragePromise
);
this.printService = printService;
this.forceRendering();

View File

@ -18,13 +18,12 @@
import { FluentBundle, FluentResource } from "fluent-bundle";
import { DOMLocalization } from "fluent-dom";
import { L10n } from "./l10n.js";
import { shadow } from "pdfjs-lib";
/**
* @implements {IL10n}
*/
class ConstL10n extends L10n {
static #instance;
constructor(lang) {
super({ lang });
this.setL10n(
@ -51,7 +50,7 @@ class ConstL10n extends L10n {
}
static get instance() {
return (this.#instance ||= new ConstL10n("en-US"));
return shadow(this, "instance", new ConstL10n("en-US"));
}
}

View File

@ -37,18 +37,16 @@ class PasswordPrompt {
/**
* @param {PasswordPromptOptions} options
* @param {OverlayManager} overlayManager - Manager for the viewer overlays.
* @param {IL10n} l10n - Localization service.
* @param {boolean} [isViewerEmbedded] - If the viewer is embedded, in e.g.
* an <iframe> or an <object>. The default value is `false`.
*/
constructor(options, overlayManager, l10n, isViewerEmbedded = false) {
constructor(options, overlayManager, isViewerEmbedded = false) {
this.dialog = options.dialog;
this.label = options.label;
this.input = options.input;
this.submitButton = options.submitButton;
this.cancelButton = options.cancelButton;
this.overlayManager = overlayManager;
this.l10n = l10n;
this._isViewerEmbedded = isViewerEmbedded;
// Attach the event listeners.
@ -84,7 +82,8 @@ class PasswordPrompt {
if (!this._isViewerEmbedded || passwordIncorrect) {
this.input.focus();
}
this.label.textContent = await this.l10n.get(
this.label.setAttribute(
"data-l10n-id",
`pdfjs-password-${passwordIncorrect ? "invalid" : "label"}`
);
}

View File

@ -27,7 +27,7 @@ const MATCHES_COUNT_LIMIT = 1000;
class PDFFindBar {
#resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
constructor(options, eventBus, l10n) {
constructor(options, eventBus) {
this.opened = false;
this.bar = options.bar;
@ -42,7 +42,6 @@ class PDFFindBar {
this.findPreviousButton = options.findPreviousButton;
this.findNextButton = options.findNextButton;
this.eventBus = eventBus;
this.l10n = l10n;
// Add event listeners to the DOM elements.
this.toggleButton.addEventListener("click", () => {
@ -109,8 +108,9 @@ class PDFFindBar {
}
updateUIState(state, previous, matchesCount) {
let findMsg = Promise.resolve("");
let status = "";
const { findField, findMsg } = this;
let findMsgId = "",
status = "";
switch (state) {
case FindState.FOUND:
@ -119,39 +119,46 @@ class PDFFindBar {
status = "pending";
break;
case FindState.NOT_FOUND:
findMsg = this.l10n.get("pdfjs-find-not-found");
findMsgId = "pdfjs-find-not-found";
status = "notFound";
break;
case FindState.WRAPPED:
findMsg = this.l10n.get(
`pdfjs-find-reached-${previous ? "top" : "bottom"}`
);
findMsgId = `pdfjs-find-reached-${previous ? "top" : "bottom"}`;
break;
}
this.findField.setAttribute("data-status", status);
this.findField.setAttribute("aria-invalid", state === FindState.NOT_FOUND);
findField.setAttribute("data-status", status);
findField.setAttribute("aria-invalid", state === FindState.NOT_FOUND);
findMsg.then(msg => {
this.findMsg.setAttribute("data-status", status);
this.findMsg.textContent = msg;
});
findMsg.setAttribute("data-status", status);
if (findMsgId) {
findMsg.setAttribute("data-l10n-id", findMsgId);
} else {
findMsg.removeAttribute("data-l10n-id");
findMsg.textContent = "";
}
this.updateResultsCount(matchesCount);
}
updateResultsCount({ current = 0, total = 0 } = {}) {
const limit = MATCHES_COUNT_LIMIT;
let matchCountMsg = Promise.resolve("");
const { findResultsCount } = this;
if (total > 0) {
matchCountMsg =
total > limit
? this.l10n.get("pdfjs-find-match-count-limit", { limit })
: this.l10n.get("pdfjs-find-match-count", { current, total });
const limit = MATCHES_COUNT_LIMIT,
isLimited = total > limit;
findResultsCount.setAttribute(
"data-l10n-id",
`pdfjs-find-match-count${isLimited ? "-limit" : ""}`
);
findResultsCount.setAttribute(
"data-l10n-args",
JSON.stringify(isLimited ? { limit } : { current, total })
);
} else {
findResultsCount.removeAttribute("data-l10n-id");
findResultsCount.textContent = "";
}
matchCountMsg.then(msg => {
this.findResultsCount.textContent = msg;
});
}
open() {

View File

@ -19,7 +19,6 @@ import { BaseTreeViewer } from "./base_tree_viewer.js";
* @typedef {Object} PDFLayerViewerOptions
* @property {HTMLDivElement} container - The viewer element.
* @property {EventBus} eventBus - The application event bus.
* @property {IL10n} l10n - Localization service.
*/
/**
@ -32,7 +31,6 @@ import { BaseTreeViewer } from "./base_tree_viewer.js";
class PDFLayerViewer extends BaseTreeViewer {
constructor(options) {
super(options);
this.l10n = options.l10n;
this.eventBus._on("optionalcontentconfigchanged", evt => {
this.#updateLayers(evt.promise);
@ -89,7 +87,7 @@ class PDFLayerViewer extends BaseTreeViewer {
/**
* @private
*/
async _setNestedName(element, { name = null }) {
_setNestedName(element, { name = null }) {
if (typeof name === "string") {
element.textContent = this._normalizeTextContent(name);
return;

View File

@ -182,9 +182,8 @@ class PDFPageView {
div.className = "page";
div.setAttribute("data-page-number", this.id);
div.setAttribute("role", "region");
this.l10n.get("pdfjs-page-landmark", { page: this.id }).then(msg => {
div.setAttribute("aria-label", msg);
});
div.setAttribute("data-l10n-id", "pdfjs-page-landmark");
div.setAttribute("data-l10n-args", JSON.stringify({ page: this.id }));
this.div = div;
this.#setDimensions();
@ -878,7 +877,6 @@ class PDFPageView {
renderForms: this.#annotationMode === AnnotationMode.ENABLE_FORMS,
linkService,
downloadManager,
l10n,
enableScripting,
hasJSActionsPromise,
fieldObjectsPromise,

View File

@ -69,8 +69,7 @@ class PDFPrintService {
printContainer,
printResolution,
optionalContentConfigPromise = null,
printAnnotationStoragePromise = null,
l10n
printAnnotationStoragePromise = null
) {
this.pdfDocument = pdfDocument;
this.pagesOverview = pagesOverview;
@ -80,7 +79,6 @@ class PDFPrintService {
optionalContentConfigPromise || pdfDocument.getOptionalContentConfig();
this._printAnnotationStoragePromise =
printAnnotationStoragePromise || Promise.resolve();
this.l10n = l10n;
this.currentPage = -1;
// The temporary canvas where renderPage paints one page at a time.
this.scratchCanvas = document.createElement("canvas");
@ -151,12 +149,12 @@ class PDFPrintService {
const renderNextPage = (resolve, reject) => {
this.throwIfInactive();
if (++this.currentPage >= pageCount) {
renderProgress(pageCount, pageCount, this.l10n);
renderProgress(pageCount, pageCount);
resolve();
return;
}
const index = this.currentPage;
renderProgress(index, pageCount, this.l10n);
renderProgress(index, pageCount);
renderPage(
this,
this.pdfDocument,
@ -288,7 +286,7 @@ function abort() {
}
}
function renderProgress(index, total, l10n) {
function renderProgress(index, total) {
if (typeof PDFJSDev === "undefined" && window.isGECKOVIEW) {
return;
}
@ -297,9 +295,7 @@ function renderProgress(index, total, l10n) {
const progressBar = dialog.querySelector("progress");
const progressPerc = dialog.querySelector(".relative-progress");
progressBar.value = progress;
l10n.get("pdfjs-print-progress-percent", { progress }).then(msg => {
progressPerc.textContent = msg;
});
progressPerc.setAttribute("data-l10n-args", JSON.stringify({ progress }));
}
window.addEventListener(
@ -368,8 +364,7 @@ PDFPrintServiceFactory.instance = {
printContainer,
printResolution,
optionalContentConfigPromise,
printAnnotationStoragePromise,
l10n
printAnnotationStoragePromise
) {
if (activeService) {
throw new Error("The print service is created and active.");
@ -380,8 +375,7 @@ PDFPrintServiceFactory.instance = {
printContainer,
printResolution,
optionalContentConfigPromise,
printAnnotationStoragePromise,
l10n
printAnnotationStoragePromise
);
return activeService;
},

View File

@ -111,7 +111,6 @@ class PDFSidebar {
this._currentOutlineItemButton = elements.currentOutlineItemButton;
this.eventBus = eventBus;
this.l10n = l10n;
this.#isRTL = l10n.getDirection() === "rtl";
this.#addEventListeners();

View File

@ -18,7 +18,6 @@
// eslint-disable-next-line max-len
/** @typedef {import("../src/display/display_utils").PageViewport} PageViewport */
/** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IL10n} IL10n */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
/** @typedef {import("./interfaces").IRenderableView} IRenderableView */
// eslint-disable-next-line max-len
@ -42,7 +41,6 @@ const THUMBNAIL_WIDTH = 98; // px
* The default value is `null`.
* @property {IPDFLinkService} linkService - The navigation/linking service.
* @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
* @property {IL10n} l10n - Localization service.
* @property {Object} [pageColors] - Overwrites background and foreground colors
* with user defined ones in order to improve readability in high contrast
* mode.
@ -93,7 +91,6 @@ class PDFThumbnailView {
optionalContentConfigPromise,
linkService,
renderingQueue,
l10n,
pageColors,
}) {
this.id = id;
@ -114,13 +111,11 @@ class PDFThumbnailView {
this.renderTask = null;
this.renderingState = RenderingStates.INITIAL;
this.resume = null;
this.l10n = l10n;
const anchor = document.createElement("a");
anchor.href = linkService.getAnchorUrl("#page=" + id);
this._thumbPageTitle.then(msg => {
anchor.title = msg;
});
anchor.setAttribute("data-l10n-id", "pdfjs-thumb-page-title");
anchor.setAttribute("data-l10n-args", this.#pageL10nArgs);
anchor.onclick = function () {
linkService.goToPage(id);
return false;
@ -232,9 +227,8 @@ class PDFThumbnailView {
const image = document.createElement("img");
image.className = "thumbnailImage";
this._thumbPageCanvas.then(msg => {
image.setAttribute("aria-label", msg);
});
image.setAttribute("data-l10n-id", "pdfjs-thumb-page-canvas");
image.setAttribute("data-l10n-args", this.#pageL10nArgs);
image.src = reducedCanvas.toDataURL();
this.image = image;
@ -423,16 +417,8 @@ class PDFThumbnailView {
return canvas;
}
get _thumbPageTitle() {
return this.l10n.get("pdfjs-thumb-page-title", {
page: this.pageLabel ?? this.id,
});
}
get _thumbPageCanvas() {
return this.l10n.get("pdfjs-thumb-page-canvas", {
page: this.pageLabel ?? this.id,
});
get #pageL10nArgs() {
return JSON.stringify({ page: this.pageLabel ?? this.id });
}
/**
@ -441,17 +427,12 @@ class PDFThumbnailView {
setPageLabel(label) {
this.pageLabel = typeof label === "string" ? label : null;
this._thumbPageTitle.then(msg => {
this.anchor.title = msg;
});
this.anchor.setAttribute("data-l10n-args", this.#pageL10nArgs);
if (this.renderingState !== RenderingStates.FINISHED) {
return;
}
this._thumbPageCanvas.then(msg => {
this.image?.setAttribute("aria-label", msg);
});
this.image?.setAttribute("data-l10n-args", this.#pageL10nArgs);
}
}

View File

@ -16,7 +16,6 @@
/** @typedef {import("../src/display/api").PDFDocumentProxy} PDFDocumentProxy */
/** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */
/** @typedef {import("./event_utils").EventBus} EventBus */
/** @typedef {import("./interfaces").IL10n} IL10n */
/** @typedef {import("./interfaces").IPDFLinkService} IPDFLinkService */
// eslint-disable-next-line max-len
/** @typedef {import("./pdf_rendering_queue").PDFRenderingQueue} PDFRenderingQueue */
@ -40,7 +39,6 @@ const THUMBNAIL_SELECTED_CLASS = "selected";
* @property {EventBus} eventBus - The application event bus.
* @property {IPDFLinkService} linkService - The navigation/linking service.
* @property {PDFRenderingQueue} renderingQueue - The rendering queue object.
* @property {IL10n} l10n - Localization service.
* @property {Object} [pageColors] - Overwrites background and foreground colors
* with user defined ones in order to improve readability in high contrast
* mode.
@ -58,14 +56,12 @@ class PDFThumbnailViewer {
eventBus,
linkService,
renderingQueue,
l10n,
pageColors,
}) {
this.container = container;
this.eventBus = eventBus;
this.linkService = linkService;
this.renderingQueue = renderingQueue;
this.l10n = l10n;
this.pageColors = pageColors || null;
this.scroll = watchScroll(this.container, this._scrollUpdated.bind(this));
@ -209,7 +205,6 @@ class PDFThumbnailViewer {
optionalContentConfigPromise,
linkService: this.linkService,
renderingQueue: this.renderingQueue,
l10n: this.l10n,
pageColors: this.pageColors,
});
this._thumbnails.push(thumbnail);

View File

@ -28,10 +28,9 @@ class Toolbar {
/**
* @param {ToolbarOptions} options
* @param {EventBus} eventBus
* @param {IL10n} _l10n - Localization service.
* @param {Object} nimbusData - Nimbus configuration.
*/
constructor(options, eventBus, _l10n, nimbusData) {
constructor(options, eventBus, nimbusData) {
this.#eventBus = eventBus;
const buttons = [
{

View File

@ -49,12 +49,10 @@ class Toolbar {
/**
* @param {ToolbarOptions} options
* @param {EventBus} eventBus
* @param {IL10n} l10n - Localization service.
*/
constructor(options, eventBus, l10n) {
constructor(options, eventBus) {
this.toolbar = options.container;
this.eventBus = eventBus;
this.l10n = l10n;
this.buttons = [
{ element: options.previous, eventName: "previouspage" },
{ element: options.next, eventName: "nextpage" },
@ -252,22 +250,27 @@ class Toolbar {
if (resetNumPages) {
if (this.hasPageLabels) {
items.pageNumber.type = "text";
items.numPages.setAttribute("data-l10n-id", "pdfjs-page-of-pages");
} else {
items.pageNumber.type = "number";
this.l10n.get("pdfjs-of-pages", { pagesCount }).then(msg => {
items.numPages.textContent = msg;
});
items.numPages.setAttribute("data-l10n-id", "pdfjs-of-pages");
items.numPages.setAttribute(
"data-l10n-args",
JSON.stringify({ pagesCount })
);
}
items.pageNumber.max = pagesCount;
}
if (this.hasPageLabels) {
items.pageNumber.value = this.pageLabel;
this.l10n
.get("pdfjs-page-of-pages", { pageNumber, pagesCount })
.then(msg => {
items.numPages.textContent = msg;
});
items.numPages.setAttribute(
"data-l10n-args",
JSON.stringify({ pageNumber, pagesCount })
);
} else {
items.pageNumber.value = pageNumber;
}
@ -278,11 +281,6 @@ class Toolbar {
items.zoomOut.disabled = pageScale <= MIN_SCALE;
items.zoomIn.disabled = pageScale >= MAX_SCALE;
this.l10n
.get("pdfjs-page-scale-percent", {
scale: Math.round(pageScale * 10000) / 100,
})
.then(msg => {
let predefinedValueFound = false;
for (const option of items.scaleSelect.options) {
if (option.value !== pageScaleValue) {
@ -293,10 +291,14 @@ class Toolbar {
predefinedValueFound = true;
}
if (!predefinedValueFound) {
items.customScaleOption.textContent = msg;
items.customScaleOption.selected = true;
items.customScaleOption.setAttribute(
"data-l10n-args",
JSON.stringify({
scale: Math.round(pageScale * 10000) / 100,
})
);
}
});
}
updateLoadingIndicatorState(loading = false) {

View File

@ -379,7 +379,7 @@ See https://github.com/adobe-type-tools/cmap-resources
<option id="pageActualOption" title="" value="page-actual" data-l10n-id="pdfjs-page-scale-actual">Actual Size</option>
<option id="pageFitOption" title="" value="page-fit" data-l10n-id="pdfjs-page-scale-fit">Page Fit</option>
<option id="pageWidthOption" title="" value="page-width" data-l10n-id="pdfjs-page-scale-width">Page Width</option>
<option id="customScaleOption" title="" value="custom" disabled="disabled" hidden="true"></option>
<option id="customScaleOption" title="" value="custom" disabled="disabled" hidden="true" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 0 }'>0%</option>
<option title="" value="0.5" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 50 }'>50%</option>
<option title="" value="0.75" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 75 }'>75%</option>
<option title="" value="1" data-l10n-id="pdfjs-page-scale-percent" data-l10n-args='{ "scale": 100 }'>100%</option>