diff --git a/src/core/best-practices.js b/src/core/best-practices.js
index ea48d5f2d1..557b8154ea 100644
--- a/src/core/best-practices.js
+++ b/src/core/best-practices.js
@@ -12,6 +12,7 @@ export const name = "core/best-practices";
const localizationStrings = {
en: {
best_practice: "Best Practice ",
+ best_practice_summary: "Best Practices Summary",
},
ja: {
best_practice: "最良実施例 ",
@@ -22,6 +23,10 @@ const localizationStrings = {
zh: {
best_practice: "最佳实践 ",
},
+ fr: {
+ best_practice: "Bonne pratique ",
+ best_practice_summary: "Résumé des bonnes pratiques",
+ },
};
const l10n = getIntlData(localizationStrings);
const lang = defaultLang in localizationStrings ? defaultLang : "en";
@@ -33,8 +38,13 @@ export function run() {
const summaryItems = bpSummary ? document.createElement("ul") : null;
[...bps].forEach((bp, num) => {
const id = addId(bp, "bp");
+ const customLabel = bp.dataset.label;
+ const rawLabel = customLabel || l10n.best_practice;
+ const label = `${rawLabel.trimEnd()} `;
+ const bdi = html`${label}${num + 1}`;
+ if (!customLabel) bdi.lang = lang;
const localizedBpName = html`${l10n.best_practice}${num + 1}${bdi}`;
// Make the summary items, if we have a summary
@@ -57,7 +67,9 @@ export function run() {
});
if (bps.length) {
if (bpSummary) {
- bpSummary.appendChild(html`
Best Practices Summary
`);
+ const summaryLabel =
+ bpSummary.dataset.label || l10n.best_practice_summary;
+ bpSummary.appendChild(html`${summaryLabel}
`);
if (summaryItems) bpSummary.appendChild(summaryItems);
}
} else if (bpSummary) {
diff --git a/tests/spec/core/best-practices-spec.js b/tests/spec/core/best-practices-spec.js
index 6d4a1fdd77..6dc31781e7 100644
--- a/tests/spec/core/best-practices-spec.js
+++ b/tests/spec/core/best-practices-spec.js
@@ -81,4 +81,79 @@ describe("Core — Best Practices", () => {
);
expect(bps.querySelectorAll("ul li")).toHaveSize(3);
});
+
+ it("uses custom labels from data-label attribute", async () => {
+ const body = `
+
+ `;
+ const ops = {
+ config: makeBasicConfig(),
+ body,
+ };
+ const doc = await makeRSDoc(ops);
+ const summary = doc.getElementById("bp-summary");
+ expect(summary).toBeTruthy();
+ const listItems = summary.querySelectorAll("li");
+ expect(listItems[0].textContent.trim()).toBe("Principle 1: P1");
+ expect(listItems[1].textContent.trim()).toBe("Principle 2: P2");
+ const heading = summary.querySelector("h3");
+ expect(heading.textContent).toContain("Principles Summary");
+
+ // Boxed practice: verify custom label appears in the visible marker
+ const selfLink = doc.querySelector(".advisement .self-link");
+ expect(selfLink.textContent).toBe("Principle 2");
+
+ // Custom labels must not carry the built-in locale's lang attribute
+ const bdi = selfLink.querySelector("bdi");
+ expect(bdi.hasAttribute("lang")).toBeFalse();
+ });
+
+ it("sets lang attribute on bdi only for built-in localized labels", async () => {
+ const body = `
+
+ `;
+ const ops = {
+ config: makeBasicConfig(),
+ body,
+ };
+ const doc = await makeRSDoc(ops);
+ const bdi = doc.querySelector(".advisement .self-link bdi");
+ expect(bdi.hasAttribute("lang")).toBeTrue();
+ });
+
+ it("uses custom labels in boxed best practice containers", async () => {
+ const body = `
+
+ Section
+
+
Boxed P1
+
Details here.
+
+
+ `;
+ const ops = {
+ config: makeBasicConfig(),
+ body,
+ };
+ const doc = await makeRSDoc(ops);
+ const container = doc.querySelector(".advisement");
+ expect(container).toBeTruthy();
+ const marker = container.querySelector(".marker");
+ expect(marker.textContent).toContain("Principle 1");
+ const bdi = marker.querySelector("bdi");
+ expect(bdi.hasAttribute("lang")).toBeFalse();
+ });
});