The issue you're experiencing is expected behavior. When you put {getLocalizedRoute(locale, '/contact')} inside a JSON string, it's just a plain string — it's never evaluated as JavaScript. The set:html directive injects the raw string as HTML, so the curly braces are treated as literal characters, not as a template expression.
The solution is to process the answer string in your Astro component before passing it to set:html, replacing a placeholder with the actual resolved URL.
Here's one approach:
1. Use a placeholder in your JSON instead of a JS expression:
{
"question": "Can my child have an extra bed?",
"answer": "<a href=\"{{contactUrl}}\">Contact</a> me directly to discuss the details."
}
2. Resolve the URL and replace the placeholder in your Astro component:
---
import { getRelativeLocaleUrl } from 'astro:i18n';
const contactUrl = getRelativeLocaleUrl(Astro.currentLocale ?? 'en', 'contact');
const processedAnswer = item.answer.replace('{{contactUrl}}', contactUrl);
---
<p set:html={processedAnswer} />
This way, the URL is computed at build/render time in Astro where JavaScript expressions are valid, and then injected into the HTML string before it's rendered. [i18n API Reference] [set:html directive]
⚠️ Remember that set:html does not escape its value, so make sure the content you're injecting is trusted. [set:html directive]
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: