fix(front-end): seo improvemnts
Some checks failed
Build and Deploy / build-and-push (push) Has been cancelled
Build and Deploy / deploy (push) Has been cancelled
PR Checks / security-sast (pull_request) Successful in 30s
PR Checks / test-backend (pull_request) Successful in 27s
Build and Deploy / test-frontend (push) Has been cancelled
Build and Deploy / test-backend (push) Has been cancelled
PR Checks / prettier-autofix (pull_request) Successful in 10s
PR Checks / test-frontend (pull_request) Successful in 1m6s
Some checks failed
Build and Deploy / build-and-push (push) Has been cancelled
Build and Deploy / deploy (push) Has been cancelled
PR Checks / security-sast (pull_request) Successful in 30s
PR Checks / test-backend (pull_request) Successful in 27s
Build and Deploy / test-frontend (push) Has been cancelled
Build and Deploy / test-backend (push) Has been cancelled
PR Checks / prettier-autofix (pull_request) Successful in 10s
PR Checks / test-frontend (pull_request) Successful in 1m6s
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
<xhtml:link rel="alternate" hreflang="en-CH" href="https://3d-fab.ch/en" />
|
<xhtml:link rel="alternate" hreflang="en-CH" href="https://3d-fab.ch/en" />
|
||||||
<xhtml:link rel="alternate" hreflang="de-CH" href="https://3d-fab.ch/de" />
|
<xhtml:link rel="alternate" hreflang="de-CH" href="https://3d-fab.ch/de" />
|
||||||
<xhtml:link rel="alternate" hreflang="fr-CH" href="https://3d-fab.ch/fr" />
|
<xhtml:link rel="alternate" hreflang="fr-CH" href="https://3d-fab.ch/fr" />
|
||||||
<xhtml:link rel="alternate" hreflang="x-default" href="https://3d-fab.ch/it" />
|
<xhtml:link rel="alternate" hreflang="x-default" href="https://3d-fab.ch/" />
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>1.0</priority>
|
<priority>1.0</priority>
|
||||||
</url>
|
</url>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<xhtml:link rel="alternate" hreflang="en-CH" href="https://3d-fab.ch/en" />
|
<xhtml:link rel="alternate" hreflang="en-CH" href="https://3d-fab.ch/en" />
|
||||||
<xhtml:link rel="alternate" hreflang="de-CH" href="https://3d-fab.ch/de" />
|
<xhtml:link rel="alternate" hreflang="de-CH" href="https://3d-fab.ch/de" />
|
||||||
<xhtml:link rel="alternate" hreflang="fr-CH" href="https://3d-fab.ch/fr" />
|
<xhtml:link rel="alternate" hreflang="fr-CH" href="https://3d-fab.ch/fr" />
|
||||||
<xhtml:link rel="alternate" hreflang="x-default" href="https://3d-fab.ch/it" />
|
<xhtml:link rel="alternate" hreflang="x-default" href="https://3d-fab.ch/" />
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>1.0</priority>
|
<priority>1.0</priority>
|
||||||
</url>
|
</url>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
<xhtml:link rel="alternate" hreflang="en-CH" href="https://3d-fab.ch/en" />
|
<xhtml:link rel="alternate" hreflang="en-CH" href="https://3d-fab.ch/en" />
|
||||||
<xhtml:link rel="alternate" hreflang="de-CH" href="https://3d-fab.ch/de" />
|
<xhtml:link rel="alternate" hreflang="de-CH" href="https://3d-fab.ch/de" />
|
||||||
<xhtml:link rel="alternate" hreflang="fr-CH" href="https://3d-fab.ch/fr" />
|
<xhtml:link rel="alternate" hreflang="fr-CH" href="https://3d-fab.ch/fr" />
|
||||||
<xhtml:link rel="alternate" hreflang="x-default" href="https://3d-fab.ch/it" />
|
<xhtml:link rel="alternate" hreflang="x-default" href="https://3d-fab.ch/" />
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>1.0</priority>
|
<priority>1.0</priority>
|
||||||
</url>
|
</url>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
<xhtml:link rel="alternate" hreflang="en-CH" href="https://3d-fab.ch/en" />
|
<xhtml:link rel="alternate" hreflang="en-CH" href="https://3d-fab.ch/en" />
|
||||||
<xhtml:link rel="alternate" hreflang="de-CH" href="https://3d-fab.ch/de" />
|
<xhtml:link rel="alternate" hreflang="de-CH" href="https://3d-fab.ch/de" />
|
||||||
<xhtml:link rel="alternate" hreflang="fr-CH" href="https://3d-fab.ch/fr" />
|
<xhtml:link rel="alternate" hreflang="fr-CH" href="https://3d-fab.ch/fr" />
|
||||||
<xhtml:link rel="alternate" hreflang="x-default" href="https://3d-fab.ch/it" />
|
<xhtml:link rel="alternate" hreflang="x-default" href="https://3d-fab.ch/" />
|
||||||
<changefreq>weekly</changefreq>
|
<changefreq>weekly</changefreq>
|
||||||
<priority>1.0</priority>
|
<priority>1.0</priority>
|
||||||
</url>
|
</url>
|
||||||
|
|||||||
@@ -117,6 +117,34 @@ describe('SeoService', () => {
|
|||||||
expect(ogLocaleCall?.[0].content).toBe('it_CH');
|
expect(ogLocaleCall?.[0].content).toBe('it_CH');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('uses the locale-adaptive root as x-default for home pages', () => {
|
||||||
|
createService({
|
||||||
|
url: '/de',
|
||||||
|
data: {
|
||||||
|
seoTitleKey: 'SEO.ROUTES.HOME.TITLE',
|
||||||
|
seoDescriptionKey: 'SEO.ROUTES.HOME.DESCRIPTION',
|
||||||
|
},
|
||||||
|
translations: {
|
||||||
|
'SEO.ROUTES.HOME.TITLE': '3D-Druck in Zürich | 3D fab',
|
||||||
|
'SEO.ROUTES.HOME.DESCRIPTION': '3D-Druckservice in Zürich',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const alternates = Array.from(
|
||||||
|
document.head.querySelectorAll(
|
||||||
|
'link[rel="alternate"][data-seo-managed="true"]',
|
||||||
|
),
|
||||||
|
).map((node) => ({
|
||||||
|
hreflang: node.getAttribute('hreflang'),
|
||||||
|
href: node.getAttribute('href'),
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(alternates).toContain({
|
||||||
|
hreflang: 'x-default',
|
||||||
|
href: `${document.location.origin}/`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('resolves translated route metadata for the active language', () => {
|
it('resolves translated route metadata for the active language', () => {
|
||||||
const { meta, title } = createService({
|
const { meta, title } = createService({
|
||||||
url: '/en/about',
|
url: '/en/about',
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export class SeoService {
|
|||||||
cleanPath,
|
cleanPath,
|
||||||
canonicalPath,
|
canonicalPath,
|
||||||
alternates,
|
alternates,
|
||||||
alternates.it ?? canonicalPath,
|
this.buildXDefaultPath(canonicalPath, alternates),
|
||||||
lang,
|
lang,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -119,8 +119,7 @@ export class SeoService {
|
|||||||
const alternates = this.normalizeAlternatePaths(override.alternates);
|
const alternates = this.normalizeAlternatePaths(override.alternates);
|
||||||
const xDefault =
|
const xDefault =
|
||||||
this.normalizeSeoPath(override.xDefault) ??
|
this.normalizeSeoPath(override.xDefault) ??
|
||||||
alternates?.it ??
|
this.buildXDefaultPath(canonicalPath, alternates);
|
||||||
canonicalPath;
|
|
||||||
|
|
||||||
this.applySeoValues(
|
this.applySeoValues(
|
||||||
title,
|
title,
|
||||||
@@ -162,7 +161,7 @@ export class SeoService {
|
|||||||
cleanPath,
|
cleanPath,
|
||||||
canonicalPath,
|
canonicalPath,
|
||||||
alternates,
|
alternates,
|
||||||
alternates.it ?? canonicalPath,
|
this.buildXDefaultPath(canonicalPath, alternates),
|
||||||
lang,
|
lang,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -360,6 +359,25 @@ export class SeoService {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private buildXDefaultPath(
|
||||||
|
canonicalPath: string | null,
|
||||||
|
alternates: SeoMap | null,
|
||||||
|
): string | null {
|
||||||
|
if (canonicalPath && this.isLocalizedHomePath(canonicalPath)) {
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return alternates?.it ?? canonicalPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private isLocalizedHomePath(path: string): boolean {
|
||||||
|
const segments = path.split('/').filter(Boolean);
|
||||||
|
return (
|
||||||
|
segments.length === 1 &&
|
||||||
|
this.supportedLangSet.has(segments[0] as SupportedLang)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private normalizeAlternatePaths(
|
private normalizeAlternatePaths(
|
||||||
paths: SeoMap | null | undefined,
|
paths: SeoMap | null | undefined,
|
||||||
): SeoMap | null {
|
): SeoMap | null {
|
||||||
|
|||||||
Reference in New Issue
Block a user