Skip to content
Merged
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
2 changes: 1 addition & 1 deletion astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
output: 'static',
site: process.env.PUBLIC_SITE_URL ?? 'https://dev.blackbrowedlabs.com',
trailingSlash: 'never',
trailingSlash: 'always',
i18n: {
defaultLocale: 'de',
locales: ['de', 'en'],
Expand Down
10 changes: 5 additions & 5 deletions src/components/SiteFooter.astro
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ const path = Astro.url.pathname;
const locale = getLocaleFromPath(path);
const t = getUiStrings(locale).footer;

const productsHref = locale === 'de' ? '/produkte' : '/en/products';
const aboutHref = locale === 'de' ? '/ueber' : '/en/about';
const contactHref = locale === 'de' ? '/kontakt' : '/en/contact';
const legalHref = locale === 'de' ? '/impressum' : '/en/legal';
const privacyHref = locale === 'de' ? '/datenschutz' : '/en/privacy';
const productsHref = locale === 'de' ? '/produkte/' : '/en/products/';
const aboutHref = locale === 'de' ? '/ueber/' : '/en/about/';
const contactHref = locale === 'de' ? '/kontakt/' : '/en/contact/';
const legalHref = locale === 'de' ? '/impressum/' : '/en/legal/';
const privacyHref = locale === 'de' ? '/datenschutz/' : '/en/privacy/';
---

<footer class="site-footer">
Expand Down
14 changes: 7 additions & 7 deletions src/components/SiteHeader.astro
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ const path = Astro.url.pathname;
const locale = getLocaleFromPath(path);
const t = getUiStrings(locale);

const homeHref = locale === 'de' ? '/' : '/en';
const productsHref = locale === 'de' ? '/produkte' : '/en/products';
const productsActive = path === productsHref || path.startsWith(productsHref + '/');
const aboutHref = locale === 'de' ? '/ueber' : '/en/about';
const aboutActive = path === aboutHref || path === aboutHref + '/';
const contactHref = locale === 'de' ? '/kontakt' : '/en/contact';
const contactActive = path === contactHref || path === contactHref + '/';
const homeHref = locale === 'de' ? '/' : '/en/';
const productsHref = locale === 'de' ? '/produkte/' : '/en/products/';
const productsActive = path.startsWith(productsHref);
const aboutHref = locale === 'de' ? '/ueber/' : '/en/about/';
const aboutActive = path === aboutHref;
const contactHref = locale === 'de' ? '/kontakt/' : '/en/contact/';
const contactActive = path === contactHref;
---

<header class="site-header">
Expand Down
2 changes: 1 addition & 1 deletion src/content/editorial/contact.de.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Code und Produktentwicklung auf GitHub: [blackbrowed-labs](https://github.com/bl

## Hinweis zum Datenschutz

Die Felder Name, E-Mail-Adresse und Nachricht werden ausschließlich zur Bearbeitung Ihrer Anfrage verarbeitet und an das E-Mail-Postfach lars@blackbrowedlabs.com (IONOS) zugestellt. Rechtsgrundlage ist Art. 6 Abs. 1 lit. b DSGVO bei vorvertraglichen Anfragen bzw. Art. 6 Abs. 1 lit. f DSGVO bei sonstigen Anfragen. Die Speicherung und Aufbewahrung erfolgt gemäß Abschnitt 5 der [Datenschutzerklärung](/datenschutz).
Die Felder Name, E-Mail-Adresse und Nachricht werden ausschließlich zur Bearbeitung Ihrer Anfrage verarbeitet und an das E-Mail-Postfach lars@blackbrowedlabs.com (IONOS) zugestellt. Rechtsgrundlage ist Art. 6 Abs. 1 lit. b DSGVO bei vorvertraglichen Anfragen bzw. Art. 6 Abs. 1 lit. f DSGVO bei sonstigen Anfragen. Die Speicherung und Aufbewahrung erfolgt gemäß Abschnitt 5 der [Datenschutzerklärung](/datenschutz/).
2 changes: 1 addition & 1 deletion src/content/editorial/contact.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Code and product development on GitHub: [blackbrowed-labs](https://github.com/bl

## Privacy notice

The fields Name, Email address, and Message are processed solely to handle your inquiry and are delivered to the email mailbox lars@blackbrowedlabs.com (IONOS). The legal basis is Art. 6 (1) (b) GDPR for pre-contractual inquiries or Art. 6 (1) (f) GDPR for other inquiries. Storage and retention follow Section 5 of the [Privacy Policy](/en/privacy).
The fields Name, Email address, and Message are processed solely to handle your inquiry and are delivered to the email mailbox lars@blackbrowedlabs.com (IONOS). The legal basis is Art. 6 (1) (b) GDPR for pre-contractual inquiries or Art. 6 (1) (f) GDPR for other inquiries. Storage and retention follow Section 5 of the [Privacy Policy](/en/privacy/).
40 changes: 22 additions & 18 deletions src/lib/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@
import type { Locale } from '../i18n';

/**
* Canonical path form: leading slash, no trailing slash, except the
* root path which is just "/".
* Canonical path form: leading slash, trailing slash kept (or added),
* except the root path which is just "/".
* Phase E (trailing-slash alignment) inverted this from the original
* "strip trailing slash" behaviour — kept symmetric with Astro's
* `trailingSlash: 'always'` so counterpart-map lookups and slug splits
* use the same shape Astro emits.
*/
function canonicalise(path: string): string {
if (path === '' || path === '/') return '/';
return path.endsWith('/') ? path.slice(0, -1) : path;
return path.endsWith('/') ? path : `${path}/`;
}

/**
Expand All @@ -23,25 +27,25 @@ function canonicalise(path: string): string {
* switcher renders the missing side as aria-disabled.
*/
const counterparts: Record<string, string> = {
'/': '/en',
'/en': '/',
'/ueber': '/en/about',
'/en/about': '/ueber',
'/kontakt': '/en/contact',
'/en/contact': '/kontakt',
'/impressum': '/en/legal',
'/en/legal': '/impressum',
'/datenschutz': '/en/privacy',
'/en/privacy': '/datenschutz',
'/produkte': '/en/products',
'/en/products': '/produkte',
'/404': '/en/404',
'/en/404': '/404',
'/': '/en/',
'/en/': '/',
'/ueber/': '/en/about/',
'/en/about/': '/ueber/',
'/kontakt/': '/en/contact/',
'/en/contact/': '/kontakt/',
'/impressum/': '/en/legal/',
'/en/legal/': '/impressum/',
'/datenschutz/': '/en/privacy/',
'/en/privacy/': '/datenschutz/',
'/produkte/': '/en/products/',
'/en/products/': '/produkte/',
'/404/': '/en/404/',
'/en/404/': '/404/',
};

export function getLocaleFromPath(path: string): Locale {
const canonical = canonicalise(path);
return canonical === '/en' || canonical.startsWith('/en/') ? 'en' : 'de';
return canonical.startsWith('/en/') ? 'en' : 'de';
}

export function getCounterpartUrl(path: string): string | null {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/en/about.astro
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const t = getUiStrings('en');
<BaseLayout title={`${title} — Blackbrowed Labs`} description={description}>
<nav class="breadcrumb" aria-label={t.breadcrumb.ariaLabel}>
<div class="breadcrumb__inner">
<a href="/en">Blackbrowed Labs</a>
<a href="/en/">Blackbrowed Labs</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<span class="breadcrumb__current" aria-current="page">{title}</span>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/en/contact.astro
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const t = getUiStrings('en');
<BaseLayout title={`${title} — Blackbrowed Labs`} description={description}>
<nav class="breadcrumb" aria-label={t.breadcrumb.ariaLabel}>
<div class="breadcrumb__inner">
<a href="/en">Blackbrowed Labs</a>
<a href="/en/">Blackbrowed Labs</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<span class="breadcrumb__current" aria-current="page">{title}</span>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/en/legal.astro
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const description =
<BaseLayout title={`${title} — Blackbrowed Labs`} description={description}>
<nav class="breadcrumb" aria-label={t.breadcrumb.ariaLabel}>
<div class="breadcrumb__inner">
<a href="/en">Blackbrowed Labs</a>
<a href="/en/">Blackbrowed Labs</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<span class="breadcrumb__current" aria-current="page">{title}</span>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/en/privacy.astro
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const tocItems = [

<nav class="breadcrumb" aria-label={t.breadcrumb.ariaLabel}>
<div class="breadcrumb__inner">
<a href="/en">Blackbrowed Labs</a>
<a href="/en/">Blackbrowed Labs</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<span class="breadcrumb__current" aria-current="page">{title}</span>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/en/products/[slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ const renderedReleaseBodies: string[] = await Promise.all(
<BaseLayout title={`${title} — Blackbrowed Labs`} description={description}>
<nav class="breadcrumb" aria-label={t.breadcrumb.ariaLabel}>
<div class="breadcrumb__inner">
<a href="/en">Blackbrowed Labs</a>
<a href="/en/">Blackbrowed Labs</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<a href="/en/products">Products</a>
<a href="/en/products/">Products</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<span class="breadcrumb__current" aria-current="page">{entry.data.name}</span>
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/pages/en/products/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const description =
<BaseLayout title={`${title} — Blackbrowed Labs`} description={description}>
<nav class="breadcrumb" aria-label={t.breadcrumb.ariaLabel}>
<div class="breadcrumb__inner">
<a href="/en">Blackbrowed Labs</a>
<a href="/en/">Blackbrowed Labs</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<span class="breadcrumb__current" aria-current="page">{t.productsIndex.breadcrumb}</span>
</div>
Expand Down Expand Up @@ -52,11 +52,11 @@ const description =
{products.map((entry) => (
<li class="products-index__item">
<h2 class="products-index__name">
<a href={`/en/products/${entry.data.slug}`}>{entry.data.name}</a>
<a href={`/en/products/${entry.data.slug}/`}>{entry.data.name}</a>
</h2>
<p class="products-index__tagline">{entry.data.tagline}</p>
<p class="products-index__description">{entry.data.description}</p>
<a class="products-index__more" href={`/en/products/${entry.data.slug}`}>
<a class="products-index__more" href={`/en/products/${entry.data.slug}/`}>
{t.productsIndex.populatedArrowLabel}
</a>
</li>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/produkte/[slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const renderedReleaseBodies: string[] = await Promise.all(
<div class="breadcrumb__inner">
<a href="/">Blackbrowed Labs</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<a href="/produkte">Produkte</a>
<a href="/produkte/">Produkte</a>
<span class="breadcrumb__sep" aria-hidden="true">/</span>
<span class="breadcrumb__current" aria-current="page">{entry.data.name}</span>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/produkte/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ const description =
{products.map((entry) => (
<li class="products-index__item">
<h2 class="products-index__name">
<a href={`/produkte/${entry.data.slug}`}>{entry.data.name}</a>
<a href={`/produkte/${entry.data.slug}/`}>{entry.data.name}</a>
</h2>
<p class="products-index__tagline">{entry.data.tagline}</p>
<p class="products-index__description">{entry.data.description}</p>
<a class="products-index__more" href={`/produkte/${entry.data.slug}`}>
<a class="products-index__more" href={`/produkte/${entry.data.slug}/`}>
{t.productsIndex.populatedArrowLabel}
</a>
</li>
Expand Down
Loading