From 4c89a494d6fe876335b2d2806b4f21ee316ea671 Mon Sep 17 00:00:00 2001 From: Amir Pourmand Date: Sun, 24 Aug 2025 16:53:51 +0330 Subject: [PATCH 1/4] Add localization for footnotes --- quartz/i18n/locales/de-DE.ts | 3 ++ quartz/i18n/locales/definition.ts | 3 ++ quartz/i18n/locales/en-GB.ts | 3 ++ quartz/i18n/locales/en-US.ts | 3 ++ quartz/i18n/locales/es-ES.ts | 3 ++ quartz/i18n/locales/fa-IR.ts | 3 ++ quartz/i18n/locales/fr-FR.ts | 3 ++ quartz/i18n/locales/it-IT.ts | 3 ++ quartz/i18n/locales/ja-JP.ts | 3 ++ quartz/i18n/locales/ko-KR.ts | 3 ++ quartz/i18n/locales/nl-NL.ts | 3 ++ quartz/i18n/locales/pl-PL.ts | 3 ++ quartz/i18n/locales/pt-BR.ts | 3 ++ quartz/i18n/locales/ru-RU.ts | 3 ++ quartz/i18n/locales/zh-CN.ts | 3 ++ quartz/i18n/locales/zh-TW.ts | 3 ++ quartz/plugins/transformers/footnotes.ts | 45 ++++++++++++++++++++++++ quartz/plugins/transformers/index.ts | 1 + 18 files changed, 94 insertions(+) create mode 100644 quartz/plugins/transformers/footnotes.ts diff --git a/quartz/i18n/locales/de-DE.ts b/quartz/i18n/locales/de-DE.ts index 85a7353a8..471ab476a 100644 --- a/quartz/i18n/locales/de-DE.ts +++ b/quartz/i18n/locales/de-DE.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min read`, }, + footnotes: { + title: "Fußnoten", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/definition.ts b/quartz/i18n/locales/definition.ts index ee1649abc..988520c58 100644 --- a/quartz/i18n/locales/definition.ts +++ b/quartz/i18n/locales/definition.ts @@ -61,6 +61,9 @@ export interface Translation { contentMeta: { readingTime: (variables: { minutes: number }) => string } + footnotes: { + title: string + } } pages: { rss: { diff --git a/quartz/i18n/locales/en-GB.ts b/quartz/i18n/locales/en-GB.ts index 80e52bf3c..e7f71e9c3 100644 --- a/quartz/i18n/locales/en-GB.ts +++ b/quartz/i18n/locales/en-GB.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min read`, }, + footnotes: { + title: "Footnotes", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/en-US.ts b/quartz/i18n/locales/en-US.ts index e1111e9ab..84f7b7588 100644 --- a/quartz/i18n/locales/en-US.ts +++ b/quartz/i18n/locales/en-US.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min read`, }, + footnotes: { + title: "Footnotes", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/es-ES.ts b/quartz/i18n/locales/es-ES.ts index b7e425e81..ebce9794d 100644 --- a/quartz/i18n/locales/es-ES.ts +++ b/quartz/i18n/locales/es-ES.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `Se lee en ${minutes} min`, }, + footnotes: { + title: "Notas al pie", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/fa-IR.ts b/quartz/i18n/locales/fa-IR.ts index 0300174f3..156e6146d 100644 --- a/quartz/i18n/locales/fa-IR.ts +++ b/quartz/i18n/locales/fa-IR.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `زمان تقریبی مطالعه: ${minutes} دقیقه`, }, + footnotes: { + title: "پاورقی‌ها", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/fr-FR.ts b/quartz/i18n/locales/fr-FR.ts index f6df309a6..89a6dcd82 100644 --- a/quartz/i18n/locales/fr-FR.ts +++ b/quartz/i18n/locales/fr-FR.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min de lecture`, }, + footnotes: { + title: "Notes de bas de page", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/it-IT.ts b/quartz/i18n/locales/it-IT.ts index be25bb640..6b6f36747 100644 --- a/quartz/i18n/locales/it-IT.ts +++ b/quartz/i18n/locales/it-IT.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} minuti`, }, + footnotes: { + title: "Note a piè di pagina", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/ja-JP.ts b/quartz/i18n/locales/ja-JP.ts index 3c30124d7..5ae34eb64 100644 --- a/quartz/i18n/locales/ja-JP.ts +++ b/quartz/i18n/locales/ja-JP.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min read`, }, + footnotes: { + title: "脚注", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/ko-KR.ts b/quartz/i18n/locales/ko-KR.ts index 1bca096b2..3e8eb00e8 100644 --- a/quartz/i18n/locales/ko-KR.ts +++ b/quartz/i18n/locales/ko-KR.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min read`, }, + footnotes: { + title: "각주", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/nl-NL.ts b/quartz/i18n/locales/nl-NL.ts index 8ab3b0722..13dacbcf7 100644 --- a/quartz/i18n/locales/nl-NL.ts +++ b/quartz/i18n/locales/nl-NL.ts @@ -60,6 +60,9 @@ export default { readingTime: ({ minutes }) => minutes === 1 ? "1 minuut leestijd" : `${minutes} minuten leestijd`, }, + footnotes: { + title: "Voetnoten", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/pl-PL.ts b/quartz/i18n/locales/pl-PL.ts index 544219ab2..31dc470c9 100644 --- a/quartz/i18n/locales/pl-PL.ts +++ b/quartz/i18n/locales/pl-PL.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min. czytania `, }, + footnotes: { + title: "Przypisy", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/pt-BR.ts b/quartz/i18n/locales/pt-BR.ts index e431d8ed5..7f9ee770e 100644 --- a/quartz/i18n/locales/pt-BR.ts +++ b/quartz/i18n/locales/pt-BR.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `Leitura de ${minutes} min`, }, + footnotes: { + title: "Notas de rodapé", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/ru-RU.ts b/quartz/i18n/locales/ru-RU.ts index 5534d140c..255a08337 100644 --- a/quartz/i18n/locales/ru-RU.ts +++ b/quartz/i18n/locales/ru-RU.ts @@ -60,6 +60,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `время чтения ~${minutes} мин.`, }, + footnotes: { + title: "Примечания", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/zh-CN.ts b/quartz/i18n/locales/zh-CN.ts index 09951bbb3..f5722ec9c 100644 --- a/quartz/i18n/locales/zh-CN.ts +++ b/quartz/i18n/locales/zh-CN.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes}分钟阅读`, }, + footnotes: { + title: "脚注", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/zh-TW.ts b/quartz/i18n/locales/zh-TW.ts index 4e784c06d..112a84679 100644 --- a/quartz/i18n/locales/zh-TW.ts +++ b/quartz/i18n/locales/zh-TW.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `閱讀時間約 ${minutes} 分鐘`, }, + footnotes: { + title: "腳註", + }, }, pages: { rss: { diff --git a/quartz/plugins/transformers/footnotes.ts b/quartz/plugins/transformers/footnotes.ts new file mode 100644 index 000000000..ca1d4fb2b --- /dev/null +++ b/quartz/plugins/transformers/footnotes.ts @@ -0,0 +1,45 @@ +import { QuartzTransformerPlugin } from "../types" +import { Root, Element } from "hast" +import { visit } from "unist-util-visit" +import { i18n } from "../../i18n" + +export const LocalizedFootnotes: QuartzTransformerPlugin = () => { + return { + name: "LocalizedFootnotes", + htmlPlugins(ctx) { + return [ + () => { + return (tree: Root) => { + const cfg = ctx.cfg.configuration + const locale = i18n(cfg.locale) + + visit(tree, "element", (node: Element) => { + // Find footnotes section + if (node.tagName === "section" && node.properties?.["dataFootnotes"] !== undefined) { + // Find the h2 heading inside + const heading = node.children.find(child => + child.type === "element" && child.tagName === "h2" + ) as Element + + if (heading) { + // Remove sr-only class if present + if (Array.isArray(heading.properties?.className)) { + heading.properties.className = heading.properties.className.filter( + cls => cls !== "sr-only" + ) + } + + // Replace the first text node with localized text + const textNode = heading.children.find(child => child.type === "text") + if (textNode) { + textNode.value = locale.components.footnotes.title + } + } + } + }) + } + }, + ] + }, + } +} diff --git a/quartz/plugins/transformers/index.ts b/quartz/plugins/transformers/index.ts index 8e2cd844f..f3fa06823 100644 --- a/quartz/plugins/transformers/index.ts +++ b/quartz/plugins/transformers/index.ts @@ -11,3 +11,4 @@ export { SyntaxHighlighting } from "./syntax" export { TableOfContents } from "./toc" export { HardLineBreaks } from "./linebreaks" export { RoamFlavoredMarkdown } from "./roam" +export { LocalizedFootnotes } from "./footnotes" From de97a2b3a991f5635162817447f3d0fe5d5ec275 Mon Sep 17 00:00:00 2001 From: Amir Pourmand Date: Sun, 24 Aug 2025 17:03:26 +0330 Subject: [PATCH 2/4] add config settings --- quartz.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/quartz.config.ts b/quartz.config.ts index b3db3d60d..79b3ab450 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -68,6 +68,7 @@ const config: QuartzConfig = { }), Plugin.ObsidianFlavoredMarkdown({ enableInHtmlEmbed: false }), Plugin.GitHubFlavoredMarkdown(), + Plugin.LocalizedFootnotes(), Plugin.TableOfContents(), Plugin.CrawlLinks({ markdownLinkResolution: "shortest" }), Plugin.Description(), From 09b4f072beac30c6b5cc7d410cf5c1053fe1ad80 Mon Sep 17 00:00:00 2001 From: Amir Pourmand Date: Sun, 24 Aug 2025 17:09:01 +0330 Subject: [PATCH 3/4] Add footnotes localization for multiple languages --- quartz/i18n/locales/ar-SA.ts | 3 +++ quartz/i18n/locales/ca-ES.ts | 3 +++ quartz/i18n/locales/cs-CZ.ts | 3 +++ quartz/i18n/locales/fi-FI.ts | 3 +++ quartz/i18n/locales/hu-HU.ts | 3 +++ quartz/i18n/locales/id-ID.ts | 3 +++ quartz/i18n/locales/lt-LT.ts | 3 +++ quartz/i18n/locales/nb-NO.ts | 3 +++ quartz/i18n/locales/ro-RO.ts | 3 +++ quartz/i18n/locales/th-TH.ts | 3 +++ quartz/i18n/locales/tr-TR.ts | 3 +++ quartz/i18n/locales/uk-UA.ts | 3 +++ quartz/i18n/locales/vi-VN.ts | 3 +++ 13 files changed, 39 insertions(+) diff --git a/quartz/i18n/locales/ar-SA.ts b/quartz/i18n/locales/ar-SA.ts index a1979def9..3072d7386 100644 --- a/quartz/i18n/locales/ar-SA.ts +++ b/quartz/i18n/locales/ar-SA.ts @@ -64,6 +64,9 @@ export default { ? `دقيقتان للقراءة` : `${minutes} دقائق للقراءة`, }, + footnotes: { + title: "الحواشي", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/ca-ES.ts b/quartz/i18n/locales/ca-ES.ts index 1483d9c57..d6800e650 100644 --- a/quartz/i18n/locales/ca-ES.ts +++ b/quartz/i18n/locales/ca-ES.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `Es llegeix en ${minutes} min`, }, + footnotes: { + title: "Notes a peu de pàgina", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/cs-CZ.ts b/quartz/i18n/locales/cs-CZ.ts index 87f19964f..121e41096 100644 --- a/quartz/i18n/locales/cs-CZ.ts +++ b/quartz/i18n/locales/cs-CZ.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min čtení`, }, + footnotes: { + title: "Poznámky pod čarou", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/fi-FI.ts b/quartz/i18n/locales/fi-FI.ts index 19e102a31..d13274af7 100644 --- a/quartz/i18n/locales/fi-FI.ts +++ b/quartz/i18n/locales/fi-FI.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min lukuaika`, }, + footnotes: { + title: "Alaviitteet", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/hu-HU.ts b/quartz/i18n/locales/hu-HU.ts index 2a4f07727..76e210404 100644 --- a/quartz/i18n/locales/hu-HU.ts +++ b/quartz/i18n/locales/hu-HU.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} perces olvasás`, }, + footnotes: { + title: "Lábjegyzetek", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/id-ID.ts b/quartz/i18n/locales/id-ID.ts index 813e2bb57..38ba3a736 100644 --- a/quartz/i18n/locales/id-ID.ts +++ b/quartz/i18n/locales/id-ID.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} menit baca`, }, + footnotes: { + title: "Catatan kaki", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/lt-LT.ts b/quartz/i18n/locales/lt-LT.ts index 690960c35..f9e414417 100644 --- a/quartz/i18n/locales/lt-LT.ts +++ b/quartz/i18n/locales/lt-LT.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min skaitymo`, }, + footnotes: { + title: "Išnašos", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/nb-NO.ts b/quartz/i18n/locales/nb-NO.ts index 0e415221e..0d3775369 100644 --- a/quartz/i18n/locales/nb-NO.ts +++ b/quartz/i18n/locales/nb-NO.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} min lesning`, }, + footnotes: { + title: "Fotnoter", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/ro-RO.ts b/quartz/i18n/locales/ro-RO.ts index 007d90169..9c3f7e857 100644 --- a/quartz/i18n/locales/ro-RO.ts +++ b/quartz/i18n/locales/ro-RO.ts @@ -60,6 +60,9 @@ export default { readingTime: ({ minutes }) => minutes == 1 ? `lectură de 1 minut` : `lectură de ${minutes} minute`, }, + footnotes: { + title: "Note de subsol", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/th-TH.ts b/quartz/i18n/locales/th-TH.ts index 073013196..9af0c4be9 100644 --- a/quartz/i18n/locales/th-TH.ts +++ b/quartz/i18n/locales/th-TH.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `อ่านราว ${minutes} นาที`, }, + footnotes: { + title: "เชิงอ้าง", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/tr-TR.ts b/quartz/i18n/locales/tr-TR.ts index 9c2d6d4ad..0a31ab683 100644 --- a/quartz/i18n/locales/tr-TR.ts +++ b/quartz/i18n/locales/tr-TR.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} dakika okuma süresi`, }, + footnotes: { + title: "Dipnotlar", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/uk-UA.ts b/quartz/i18n/locales/uk-UA.ts index ac2a24850..31c62c917 100644 --- a/quartz/i18n/locales/uk-UA.ts +++ b/quartz/i18n/locales/uk-UA.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `${minutes} хв читання`, }, + footnotes: { + title: "Примітки", + }, }, pages: { rss: { diff --git a/quartz/i18n/locales/vi-VN.ts b/quartz/i18n/locales/vi-VN.ts index 26a58a50e..1c3877e65 100644 --- a/quartz/i18n/locales/vi-VN.ts +++ b/quartz/i18n/locales/vi-VN.ts @@ -59,6 +59,9 @@ export default { contentMeta: { readingTime: ({ minutes }) => `đọc ${minutes} phút`, }, + footnotes: { + title: "Chú thích", + }, }, pages: { rss: { From e23c03ca252788dc3d7a5b3470b23e6ae560625d Mon Sep 17 00:00:00 2001 From: Amir Pourmand Date: Sun, 24 Aug 2025 17:12:04 +0330 Subject: [PATCH 4/4] Refactor footnotes transformer for improved localization handling - Cleaned up code formatting for better readability. - Ensured proper localization of footnote titles by replacing text nodes with localized values. - Removed unnecessary class names from headings to enhance accessibility. --- quartz/plugins/transformers/footnotes.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/quartz/plugins/transformers/footnotes.ts b/quartz/plugins/transformers/footnotes.ts index ca1d4fb2b..d697ef7c4 100644 --- a/quartz/plugins/transformers/footnotes.ts +++ b/quartz/plugins/transformers/footnotes.ts @@ -12,25 +12,25 @@ export const LocalizedFootnotes: QuartzTransformerPlugin = () => { return (tree: Root) => { const cfg = ctx.cfg.configuration const locale = i18n(cfg.locale) - + visit(tree, "element", (node: Element) => { // Find footnotes section if (node.tagName === "section" && node.properties?.["dataFootnotes"] !== undefined) { // Find the h2 heading inside - const heading = node.children.find(child => - child.type === "element" && child.tagName === "h2" + const heading = node.children.find( + (child) => child.type === "element" && child.tagName === "h2", ) as Element - + if (heading) { // Remove sr-only class if present if (Array.isArray(heading.properties?.className)) { heading.properties.className = heading.properties.className.filter( - cls => cls !== "sr-only" + (cls) => cls !== "sr-only", ) } - + // Replace the first text node with localized text - const textNode = heading.children.find(child => child.type === "text") + const textNode = heading.children.find((child) => child.type === "text") if (textNode) { textNode.value = locale.components.footnotes.title }