[Editor] Utilize Fluent "better" when localizing the AltText
Currently we manually localize and update the DOM-elements of the AltText-button, and it seems nicer to utilize Fluent "properly" for that task. This can be achieved by introducing an explicit `span`-element on the AltText-button (similar to e.g. the regular toolbar-buttons), and adding a few more l10n-strings, since that allows just setting the `data-l10n-id`-attribute on all the relevant DOM-elements. Finally, note how we no longer need to localize any strings eagerly when initializing the various editors.
This commit is contained in:
parent
9108848743
commit
ee812b5df2
@ -360,9 +360,12 @@ pdfjs-ink-canvas =
|
|||||||
## Alt-text dialog
|
## Alt-text dialog
|
||||||
|
|
||||||
# Alternative text (alt text) helps when people can't see the image.
|
# Alternative text (alt text) helps when people can't see the image.
|
||||||
|
pdfjs-editor-alt-text-button =
|
||||||
|
.aria-label = Alt text
|
||||||
pdfjs-editor-alt-text-button-label = Alt text
|
pdfjs-editor-alt-text-button-label = Alt text
|
||||||
|
|
||||||
pdfjs-editor-alt-text-edit-button-label = Edit alt text
|
pdfjs-editor-alt-text-edit-button =
|
||||||
|
.aria-label = Edit alt text
|
||||||
pdfjs-editor-alt-text-dialog-label = Choose an option
|
pdfjs-editor-alt-text-dialog-label = Choose an option
|
||||||
pdfjs-editor-alt-text-dialog-description = Alt text (alternative text) helps when people can’t see the image or when it doesn’t load.
|
pdfjs-editor-alt-text-dialog-description = Alt text (alternative text) helps when people can’t see the image or when it doesn’t load.
|
||||||
pdfjs-editor-alt-text-add-description-label = Add a description
|
pdfjs-editor-alt-text-add-description-label = Add a description
|
||||||
@ -457,12 +460,18 @@ pdfjs-editor-new-alt-text-ai-model-downloading-progress = Downloading alt text A
|
|||||||
.aria-valuetext = Downloading alt text AI model ({ $downloadedSize } of { $totalSize } MB)
|
.aria-valuetext = Downloading alt text AI model ({ $downloadedSize } of { $totalSize } MB)
|
||||||
|
|
||||||
# This is a button that users can click to edit the alt text they have already added.
|
# This is a button that users can click to edit the alt text they have already added.
|
||||||
|
pdfjs-editor-new-alt-text-added-button =
|
||||||
|
.aria-label = Alt text added
|
||||||
pdfjs-editor-new-alt-text-added-button-label = Alt text added
|
pdfjs-editor-new-alt-text-added-button-label = Alt text added
|
||||||
|
|
||||||
# This is a button that users can click to open the alt text editor and add alt text when it is not present.
|
# This is a button that users can click to open the alt text editor and add alt text when it is not present.
|
||||||
|
pdfjs-editor-new-alt-text-missing-button =
|
||||||
|
.aria-label = Missing alt text
|
||||||
pdfjs-editor-new-alt-text-missing-button-label = Missing alt text
|
pdfjs-editor-new-alt-text-missing-button-label = Missing alt text
|
||||||
|
|
||||||
# This is a button that opens up the alt text modal where users should review the alt text that was automatically generated.
|
# This is a button that opens up the alt text modal where users should review the alt text that was automatically generated.
|
||||||
|
pdfjs-editor-new-alt-text-to-review-button =
|
||||||
|
.aria-label = Review alt text
|
||||||
pdfjs-editor-new-alt-text-to-review-button-label = Review alt text
|
pdfjs-editor-new-alt-text-to-review-button-label = Review alt text
|
||||||
|
|
||||||
# "Created automatically" is a prefix that will be added to the beginning of any alt text that has been automatically generated. After the colon, the user will see/hear the actual alt text description. If the alt text has been edited by a human, this prefix will not appear.
|
# "Created automatically" is a prefix that will be added to the beginning of any alt text that has been automatically generated. After the colon, the user will see/hear the actual alt text description. If the alt text has been edited by a human, this prefix will not appear.
|
||||||
|
|||||||
@ -22,6 +22,8 @@ class AltText {
|
|||||||
|
|
||||||
#altTextButton = null;
|
#altTextButton = null;
|
||||||
|
|
||||||
|
#altTextButtonLabel = null;
|
||||||
|
|
||||||
#altTextTooltip = null;
|
#altTextTooltip = null;
|
||||||
|
|
||||||
#altTextTooltipTimeout = null;
|
#altTextTooltipTimeout = null;
|
||||||
@ -40,38 +42,46 @@ class AltText {
|
|||||||
|
|
||||||
static #l10nNewButton = null;
|
static #l10nNewButton = null;
|
||||||
|
|
||||||
static _l10nPromise = null;
|
static _l10n = null;
|
||||||
|
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
this.#editor = editor;
|
this.#editor = editor;
|
||||||
this.#useNewAltTextFlow = editor._uiManager.useNewAltTextFlow;
|
this.#useNewAltTextFlow = editor._uiManager.useNewAltTextFlow;
|
||||||
|
|
||||||
AltText.#l10nNewButton ||= Object.freeze({
|
AltText.#l10nNewButton ||= Object.freeze({
|
||||||
added: "pdfjs-editor-new-alt-text-added-button-label",
|
added: "pdfjs-editor-new-alt-text-added-button",
|
||||||
missing: "pdfjs-editor-new-alt-text-missing-button-label",
|
"added-label": "pdfjs-editor-new-alt-text-added-button-label",
|
||||||
review: "pdfjs-editor-new-alt-text-to-review-button-label",
|
missing: "pdfjs-editor-new-alt-text-missing-button",
|
||||||
|
"missing-label": "pdfjs-editor-new-alt-text-missing-button-label",
|
||||||
|
review: "pdfjs-editor-new-alt-text-to-review-button",
|
||||||
|
"review-label": "pdfjs-editor-new-alt-text-to-review-button-label",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static initialize(l10nPromise) {
|
static initialize(l10n) {
|
||||||
AltText._l10nPromise ||= l10nPromise;
|
AltText._l10n ??= l10n;
|
||||||
}
|
}
|
||||||
|
|
||||||
async render() {
|
async render() {
|
||||||
const altText = (this.#altTextButton = document.createElement("button"));
|
const altText = (this.#altTextButton = document.createElement("button"));
|
||||||
altText.className = "altText";
|
altText.className = "altText";
|
||||||
let msg;
|
altText.tabIndex = "0";
|
||||||
|
|
||||||
|
const label = (this.#altTextButtonLabel = document.createElement("span"));
|
||||||
|
altText.append(label);
|
||||||
|
|
||||||
if (this.#useNewAltTextFlow) {
|
if (this.#useNewAltTextFlow) {
|
||||||
altText.classList.add("new");
|
altText.classList.add("new");
|
||||||
msg = await AltText._l10nPromise.get(AltText.#l10nNewButton.missing);
|
altText.setAttribute("data-l10n-id", AltText.#l10nNewButton.missing);
|
||||||
} else {
|
label.setAttribute(
|
||||||
msg = await AltText._l10nPromise.get(
|
"data-l10n-id",
|
||||||
"pdfjs-editor-alt-text-button-label"
|
AltText.#l10nNewButton["missing-label"]
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
altText.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-button");
|
||||||
|
label.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-button-label");
|
||||||
}
|
}
|
||||||
altText.textContent = msg;
|
|
||||||
altText.setAttribute("aria-label", msg);
|
|
||||||
altText.tabIndex = "0";
|
|
||||||
const signal = this.#editor._uiManager._signal;
|
const signal = this.#editor._uiManager._signal;
|
||||||
altText.addEventListener("contextmenu", noContextMenu, { signal });
|
altText.addEventListener("contextmenu", noContextMenu, { signal });
|
||||||
altText.addEventListener("pointerdown", event => event.stopPropagation(), {
|
altText.addEventListener("pointerdown", event => event.stopPropagation(), {
|
||||||
@ -144,9 +154,10 @@ class AltText {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.#guessedText = guessedText;
|
this.#guessedText = guessedText;
|
||||||
this.#textWithDisclaimer = await AltText._l10nPromise.get(
|
this.#textWithDisclaimer = await AltText._l10n.get(
|
||||||
"pdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer"
|
"pdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer",
|
||||||
)({ generatedAltText: guessedText });
|
{ generatedAltText: guessedText }
|
||||||
|
);
|
||||||
this.#setState();
|
this.#setState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +240,7 @@ class AltText {
|
|||||||
destroy() {
|
destroy() {
|
||||||
this.#altTextButton?.remove();
|
this.#altTextButton?.remove();
|
||||||
this.#altTextButton = null;
|
this.#altTextButton = null;
|
||||||
|
this.#altTextButtonLabel = null;
|
||||||
this.#altTextTooltip = null;
|
this.#altTextTooltip = null;
|
||||||
this.#badge?.remove();
|
this.#badge?.remove();
|
||||||
this.#badge = null;
|
this.#badge = null;
|
||||||
@ -242,19 +254,12 @@ class AltText {
|
|||||||
|
|
||||||
if (this.#useNewAltTextFlow) {
|
if (this.#useNewAltTextFlow) {
|
||||||
button.classList.toggle("done", !!this.#altText);
|
button.classList.toggle("done", !!this.#altText);
|
||||||
AltText._l10nPromise
|
button.setAttribute("data-l10n-id", AltText.#l10nNewButton[this.#label]);
|
||||||
.get(AltText.#l10nNewButton[this.#label])
|
|
||||||
.then(msg => {
|
this.#altTextButtonLabel?.setAttribute(
|
||||||
button.setAttribute("aria-label", msg);
|
"data-l10n-id",
|
||||||
// We can't just use button.textContent here, because it would remove
|
AltText.#l10nNewButton[`${this.#label}-label`]
|
||||||
// the existing tooltip element.
|
);
|
||||||
for (const child of button.childNodes) {
|
|
||||||
if (child.nodeType === Node.TEXT_NODE) {
|
|
||||||
child.textContent = msg;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!this.#altText) {
|
if (!this.#altText) {
|
||||||
this.#altTextTooltip?.remove();
|
this.#altTextTooltip?.remove();
|
||||||
return;
|
return;
|
||||||
@ -266,11 +271,7 @@ class AltText {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
button.classList.add("done");
|
button.classList.add("done");
|
||||||
AltText._l10nPromise
|
button.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-edit-button");
|
||||||
.get("pdfjs-editor-alt-text-edit-button-label")
|
|
||||||
.then(msg => {
|
|
||||||
button.setAttribute("aria-label", msg);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let tooltip = this.#altTextTooltip;
|
let tooltip = this.#altTextTooltip;
|
||||||
@ -315,11 +316,15 @@ class AltText {
|
|||||||
{ signal }
|
{ signal }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
tooltip.innerText = this.#altTextDecorative
|
if (this.#altTextDecorative) {
|
||||||
? await AltText._l10nPromise.get(
|
tooltip.setAttribute(
|
||||||
|
"data-l10n-id",
|
||||||
"pdfjs-editor-alt-text-decorative-tooltip"
|
"pdfjs-editor-alt-text-decorative-tooltip"
|
||||||
)
|
);
|
||||||
: this.#altText;
|
} else {
|
||||||
|
tooltip.removeAttribute("data-l10n-id");
|
||||||
|
tooltip.textContent = this.#altText;
|
||||||
|
}
|
||||||
|
|
||||||
if (!tooltip.parentNode) {
|
if (!tooltip.parentNode) {
|
||||||
button.append(tooltip);
|
button.append(tooltip);
|
||||||
|
|||||||
@ -88,7 +88,7 @@ class AnnotationEditor {
|
|||||||
|
|
||||||
_focusEventsAllowed = true;
|
_focusEventsAllowed = true;
|
||||||
|
|
||||||
static _l10nPromise = null;
|
static _l10n = null;
|
||||||
|
|
||||||
static _l10nResizer = null;
|
static _l10nResizer = null;
|
||||||
|
|
||||||
@ -210,6 +210,8 @@ class AnnotationEditor {
|
|||||||
* @param {Object} l10n
|
* @param {Object} l10n
|
||||||
*/
|
*/
|
||||||
static initialize(l10n, _uiManager) {
|
static initialize(l10n, _uiManager) {
|
||||||
|
AnnotationEditor._l10n ??= l10n;
|
||||||
|
|
||||||
AnnotationEditor._l10nResizer ||= Object.freeze({
|
AnnotationEditor._l10nResizer ||= Object.freeze({
|
||||||
topLeft: "pdfjs-editor-resizer-top-left",
|
topLeft: "pdfjs-editor-resizer-top-left",
|
||||||
topMiddle: "pdfjs-editor-resizer-top-middle",
|
topMiddle: "pdfjs-editor-resizer-top-middle",
|
||||||
@ -221,21 +223,6 @@ class AnnotationEditor {
|
|||||||
middleLeft: "pdfjs-editor-resizer-middle-left",
|
middleLeft: "pdfjs-editor-resizer-middle-left",
|
||||||
});
|
});
|
||||||
|
|
||||||
AnnotationEditor._l10nPromise ||= new Map([
|
|
||||||
...[
|
|
||||||
"pdfjs-editor-alt-text-button-label",
|
|
||||||
"pdfjs-editor-alt-text-edit-button-label",
|
|
||||||
"pdfjs-editor-alt-text-decorative-tooltip",
|
|
||||||
"pdfjs-editor-new-alt-text-added-button-label",
|
|
||||||
"pdfjs-editor-new-alt-text-missing-button-label",
|
|
||||||
"pdfjs-editor-new-alt-text-to-review-button-label",
|
|
||||||
].map(str => [str, l10n.get(str)]),
|
|
||||||
...[
|
|
||||||
// Strings that need l10n-arguments.
|
|
||||||
"pdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer",
|
|
||||||
].map(str => [str, l10n.get.bind(l10n, str)]),
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (AnnotationEditor._borderLineWidth !== -1) {
|
if (AnnotationEditor._borderLineWidth !== -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1003,7 +990,7 @@ class AnnotationEditor {
|
|||||||
if (this.#altText) {
|
if (this.#altText) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AltText.initialize(AnnotationEditor._l10nPromise);
|
AltText.initialize(AnnotationEditor._l10n);
|
||||||
this.#altText = new AltText(this);
|
this.#altText = new AltText(this);
|
||||||
if (this.#accessibilityData) {
|
if (this.#accessibilityData) {
|
||||||
this.#altText.data = this.#accessibilityData;
|
this.#altText.data = this.#accessibilityData;
|
||||||
|
|||||||
@ -94,6 +94,14 @@ const copyImage = async (page, imagePath, number) => {
|
|||||||
await waitForImage(page, getEditorSelector(number));
|
await waitForImage(page, getEditorSelector(number));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function waitForTranslation(page) {
|
||||||
|
return page.evaluate(async () => {
|
||||||
|
await new Promise(resolve => {
|
||||||
|
window.requestAnimationFrame(resolve);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const switchToStamp = switchToEditor.bind(null, "Stamp");
|
const switchToStamp = switchToEditor.bind(null, "Stamp");
|
||||||
|
|
||||||
describe("Stamp Editor", () => {
|
describe("Stamp Editor", () => {
|
||||||
@ -987,6 +995,7 @@ describe("Stamp Editor", () => {
|
|||||||
const buttonSelector = `${editorSelector} button.altText.new`;
|
const buttonSelector = `${editorSelector} button.altText.new`;
|
||||||
await page.waitForSelector(buttonSelector, { visible: true });
|
await page.waitForSelector(buttonSelector, { visible: true });
|
||||||
|
|
||||||
|
await waitForTranslation(page);
|
||||||
// Check the text in the button.
|
// Check the text in the button.
|
||||||
let text = await page.evaluate(
|
let text = await page.evaluate(
|
||||||
sel => document.querySelector(sel).textContent,
|
sel => document.querySelector(sel).textContent,
|
||||||
@ -1036,6 +1045,7 @@ describe("Stamp Editor", () => {
|
|||||||
await waitForSelectedEditor(page, editorSelector);
|
await waitForSelectedEditor(page, editorSelector);
|
||||||
await page.waitForSelector(buttonSelector, { visible: true });
|
await page.waitForSelector(buttonSelector, { visible: true });
|
||||||
|
|
||||||
|
await waitForTranslation(page);
|
||||||
// Check the text in the button.
|
// Check the text in the button.
|
||||||
text = await page.evaluate(
|
text = await page.evaluate(
|
||||||
sel => document.querySelector(sel).textContent,
|
sel => document.querySelector(sel).textContent,
|
||||||
@ -1078,6 +1088,7 @@ describe("Stamp Editor", () => {
|
|||||||
await page.click("#newAltTextSave");
|
await page.click("#newAltTextSave");
|
||||||
await page.waitForSelector("#newAltTextDialog", { visible: false });
|
await page.waitForSelector("#newAltTextDialog", { visible: false });
|
||||||
|
|
||||||
|
await waitForTranslation(page);
|
||||||
// Check the text in the button.
|
// Check the text in the button.
|
||||||
text = await page.evaluate(
|
text = await page.evaluate(
|
||||||
sel => document.querySelector(sel).firstChild.textContent,
|
sel => document.querySelector(sel).firstChild.textContent,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user