Open danburzo opened 1 year ago
One possible fix for it would be to check if the page already has the correct language code in the locale_url
filter:
// Already has the correct language code
if (Comparator.urlHasLangCode(url, langCode)) {
return url;
}
I've added a second test case, default-langcode-omitted
, which coincidentally also gets fixed with the change above. This case tests whether we can omit the language prefix for the default language, with this permalink setup for the en/
folder:
/* en/en.11tydata.js */
module.exports = {
/*
With English being the default language,
remove the `/en/` prefix from all permalinks.
*/
permalink: data => {
const stem = data.page.filePathStem.replace(/^\/en\//, '');
const ext = data.page.outputFileExtension;
if (stem === 'index' || stem.match(/\/index$/)) {
return `${stem}.${ext}`;
}
return `${stem}/index.${ext}`;
}
};
In the docs, this arrangement is handled with server-side redirects, but there's nothing much in the way of doing it in Eleventy directly.
Before the fix, the template:
<a href="{{ '/my-article/' | locale_url }}">Permalink</a>
Here's the before-fix / after-fix for dist/my-article/index.html
, for the English locale:
<!-- before fix, `de` locale is picked up for English -->
<a href="/de/my-article/">Permalink</a>
<!-- after fix, correct URL -->
<a href="/my-article/">Permalink</a>
I say coincidentally fixed because I noticed some weird things, such as:
Comparator.isLangCode('my-article'); // => true
For now I've settled on a pared-down implementation for the i18n plugin that:
locales
to look for in inputPath
s, to avoid overidentifying path segments as localesinputPath
where every locale is replaced with the same string (e.g. ":locale:")locale_links
(as proposed in #2789), because it's easier to filter out current locale than to splice it in.locale_page
as I'm not using any related functionality, and Pagination probably needs some attentionconst path = require('path');
module.exports = function EleventyPlugin(config, opts = {}) {
let options = {
defaultLocale: 'en',
locales: ['en'],
...opts
};
let byCanonicalPath = {};
let byUrl = {};
config.on('eleventy.contentMap', function (map) {
Object.entries(map.urlToInputPath)
.map(function (entry) {
let locale;
return {
url: entry[0],
canonicalPath: entry[1]
.split(path.sep)
.map(function (seg) {
if (options.locales.includes(seg)) {
if (!locale) locale = seg;
return ':locale:';
}
return seg;
})
.join(path.sep),
lang: locale || options.defaultLocale,
label: `TODO[${locale}]`
};
})
.forEach(function (entry) {
if (!byCanonicalPath[entry.canonicalPath]) {
byCanonicalPath[entry.canonicalPath] = {};
}
byCanonicalPath[entry.canonicalPath][entry.lang] = entry;
byUrl[entry.url] = entry;
});
});
config.addFilter('locale_url', function (url, overrideLang) {
const lang = overrideLang || this.page?.lang || options.defaultLocale;
const canonicalPath = byUrl[url].canonicalPath;
return byCanonicalPath[canonicalPath][lang]?.url || url;
});
config.addFilter('locale_links', function (url) {
const canonicalPath = byUrl[url].canonicalPath;
return Object.values(byCanonicalPath[canonicalPath]);
});
};
Operating system
macOS Ventura 13.2
Eleventy
2.0.0-beta.3
Describe the bug
With a basic i18n setup and the default permalink schema, an error is thrown when attempting to use
locale_url
on an URL that contains the default language code in it.File structure:
Template file:
Config file:
Reproduction steps
basic-langcode
andnpm install
npm run build
The following error is displayed:
Reproduction URL
https://github.com/danburzo/eleventy-i18n-repro/tree/master/basic-langcode