Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions news/changelog-1.11.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
All changes included in 1.11:

## Formats

### All Formats

- ([#14772](https://github.com/quarto-dev/quarto-cli/issues/14772)): Custom `language` keys now reach templates through `$quarto.language.<key>$`. A key that Quarto does not ship passed schema validation and was merged over the defaults, then discarded before templates saw it, so it expanded to an empty string with no warning. (author: @mcanouil)

## Engines

### `knitr`
Expand Down
5 changes: 4 additions & 1 deletion src/core/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,13 @@ export function translationsForLang(language: FormatLanguage, lang: string) {
let translations = {} as FormatLanguage;
Object.keys(language).forEach((key) => {
// crossrefs can be custom, so be more lenient
// any other non-object value is a user or extension defined string,
// objects are locale variations and are merged below instead
if (
kLanguageDefaultsKeys.includes(key) ||
key.match(/^crossref-.*-title$/) ||
key.match(/^crossref-.*-prefix$/)
key.match(/^crossref-.*-prefix$/) ||
typeof language[key] !== "object"
) {
translations[key] = language[key];
}
Expand Down
41 changes: 41 additions & 0 deletions tests/docs/smoke-all/2026/08/13/issue-14772.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: "Custom `language` keys reach the template namespace (#14772)"
format:
typst:
template-partials:
- typst-show.typ
keep-typ: true
language:
toc-title-document: "Overridden built-in"
custom-key: "Custom value"
en:
variation-key: "Variation value"
_quarto:
tests:
typst:
ensureTypstFileRegexMatches:
-
- 'built-in overridden: `Overridden built-in`'
- 'built-in untouched: `Abstract`'
- 'custom key: `Custom value`'
- 'variation key: `Variation value`'
-
- 'custom key: ``'
- 'variation key: ``'
noErrors: true
---

Regression test for #14772. `translationsForLang` rebuilt the language table
from an allow-list, and `formatLanguage` ran it after merging the user's
`language` object over the defaults, so a key Quarto does not ship was
accepted by the schema, merged, and then discarded before templates saw it.
`$quarto.language.custom-key$` expanded to an empty string with no warning.

The four keys read back by `typst-show.typ` isolate the parts that must keep
working alongside the fix: an override of a built-in key still wins over the
default, an untouched built-in key still resolves to its default, and a
locale-variation sub-object still merges through the variation loop rather
than leaking as an object, which is what the non-object test in the filter
protects. Only the custom key regressed.

The end.
10 changes: 10 additions & 0 deletions tests/docs/smoke-all/2026/08/13/typst-show.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#show: doc => {
[built-in overridden: `$quarto.language.toc-title-document$`]
linebreak()
[built-in untouched: `$quarto.language.section-title-abstract$`]
linebreak()
[custom key: `$quarto.language.custom-key$`]
linebreak()
[variation key: `$quarto.language.variation-key$`]
doc
}
Loading