Hi everyone,
I’m currently working on a multilingual Kirby 4 site that includes a glossary page. I’ve created a custom plugin that adds a button to my custom “paragraph” field (which uses the Writer field). When I select some text and click this button, it retrieves the selected word’s slug and inserts a link to the glossary page, jumping straight to that specific entry (e.g., /glossary#my-word).
This worked perfectly before adding multilingual support because the /glossary URL was hard-coded. Now I need the URL to adapt based on the current panel language so that, for example, in French the link would be /fr/glossaire#my-word. To achieve this, I set up the code shown below. In the frontend templates, I can retrieve the correct slug depending on the language, but inside the plugin’s panel code, I always get the default language slug. It’s as if the French version doesn’t exist when running through the panel’s plugin code, even though the exact same logic works fine on the frontend.
Here’s my code:
index.php:
<?php
Kirby::plugin('vyp/kirby-glossaire-link-writer', [
'api' => [
'routes' => [
[
'pattern' => 'glossary-config',
'method' => 'GET',
'action' => function () {
$panelLanguageCode = get('language', kirby()->panelLanguage());
$glossaryPage = page('glossary');
if ($panelLanguageCode == 'en') {
$panelLanguageCode = '';
}
$path = $panelLanguageCode . '/' . $glossaryPage->slug();
return [
'slug' => $path
];
},
'auth' => false
]
]
]
]);
index.js:
let glossarySlug = '';
fetch('/api/glossary-config')
.then(response => response.json())
.then(data => {
glossarySlug = data.slug;
console.log('Glossary slug loaded:', glossarySlug);
})
.catch(error => console.error('Error loading slug:', error));
window.panel.plugin("vyp/kirby-glossaire-link-writer", {
writerMarks: {
glossary: {
get button() {
return {
icon: "order-alpha-asc",
label: "Glossary Link",
command: "glossaire"
};
},
commands({ type }) {
return {
glossaire: () => {
return (state, dispatch) => {
if (!state || !state.selection || state.selection.empty) {
return false;
}
const { from, to } = state.selection;
const selectedText = state.doc.textBetween(from, to, " ");
if (!selectedText) {
return false;
}
const slug = selectedText.toLowerCase().replace(/\s+/g, '-');
const mark = type.create({ slug: slug });
if (dispatch) {
const tr = state.tr.addMark(from, to, mark);
dispatch(tr);
return true;
}
return false;
};
}
};
},
get name() {
return "glossary";
},
get schema() {
return {
attrs: {
slug: { default: '' }
},
inclusive: false,
parseDOM: [{
tag: "a.glossaire__link",
priority: 51,
getAttrs(dom) {
const href = dom.getAttribute("href") || "";
const match = href.match(/\/[^/]+#([^]+)/);
const slug = match ? match[1] : dom.textContent.trim().toLowerCase().replace(/\s+/g, '-');
return { slug: slug };
}
}],
toDOM(node) {
return [
"a",
{
class: "glossaire__link",
href: `/${glossarySlug}#${node.attrs.slug}`
},
0
];
}
};
},
},
},
});
As mentioned, this approach returns the correct localized slug in the frontend, but in the panel (via the plugin) it always falls back to the default language slug. I suspect this might be related to how the panel language is determined or passed to the API route, but I haven’t been able to find a solution yet.
Has anyone encountered a similar issue or can suggest a way to make sure the plugin’s API route returns the correct localized slug depending on the panel language?
Thanks in advance!