Skip to content

Commit 328e145

Browse files
Philipp Zerellespzerelles
authored andcommitted
Added i18n routes to default template demonstrating alternate pages
1 parent f068a72 commit 328e145

File tree

5 files changed

+111
-5
lines changed

5 files changed

+111
-5
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import locales from './locales.js';
2+
3+
export const defaultLocale = locales[0];
4+
5+
/** @typedef {{
6+
* content: string;
7+
* dynamic: boolean;
8+
* spread: boolean;
9+
* }} Part */
10+
11+
/**
12+
* Create localized routes prefixed with locale
13+
* @param {Part[][]} segments
14+
* @param {'page' | 'endpoint'} type
15+
* @returns {Part[][][]}
16+
*/
17+
export function localizeRoutes(segments, type) {
18+
if (type === 'endpoint') return [segments];
19+
return locales.map((locale) =>
20+
locale === defaultLocale
21+
? segments
22+
: [
23+
[{ content: locale, dynamic: false, spread: false }],
24+
...segments.map((segment) => segment.map((part) => translate(part)))
25+
]
26+
);
27+
}
28+
29+
/**
30+
* Translate part of a route segment
31+
* @param {Part} part
32+
* @returns {Part}
33+
*/
34+
function translate(part) {
35+
if (part.content === 'about') return { ...part, content: 'ueber' };
36+
return part;
37+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default ['en', 'de'];

packages/create-svelte/templates/default/src/lib/Header/index.svelte

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
<script lang="ts">
22
import { page } from '$app/stores';
33
import logo from './svelte-logo.svg';
4+
import { l, localizedPaths, locale as currentLocale, defaultLocale } from '$lib/i18n';
5+
6+
$: alternatePaths = $localizedPaths($page.path) || {};
7+
$: defaultPath = alternatePaths[defaultLocale];
48
</script>
59

10+
<svelte:head>
11+
{#if defaultPath}
12+
<link rel="alternate" hreflang="x-default" href={defaultPath} />
13+
{/if}
14+
{#each Object.entries(alternatePaths) as [locale, path]}
15+
<link rel="alternate" hreflang={locale} href={path} />
16+
{/each}
17+
</svelte:head>
18+
619
<header>
720
<div class="corner">
821
<a href="https://kit.svelte.dev">
@@ -15,9 +28,13 @@
1528
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
1629
</svg>
1730
<ul>
18-
<li class:active={$page.path === '/'}><a sveltekit:prefetch href="/">Home</a></li>
19-
<li class:active={$page.path === '/about'}><a sveltekit:prefetch href="/about">About</a></li>
20-
<li class:active={$page.path === '/todos'}><a sveltekit:prefetch href="/todos">Todos</a></li>
31+
<li class:active={$page.path === $l('/')}><a sveltekit:prefetch href={$l('/')}>Home</a></li>
32+
<li class:active={$page.path === $l('/about')}>
33+
<a sveltekit:prefetch href={$l('/about')}>About</a>
34+
</li>
35+
<li class:active={$page.path === $l('/todos')}>
36+
<a sveltekit:prefetch href={$l('/todos')}>Todos</a>
37+
</li>
2138
</ul>
2239
<svg viewBox="0 0 2 3" aria-hidden="true">
2340
<path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" />
@@ -26,6 +43,11 @@
2643

2744
<div class="corner">
2845
<!-- TODO put something else here? github link? -->
46+
<nav>
47+
{#each Object.entries(alternatePaths) as [locale, path]}
48+
<a class:active={$currentLocale === locale} href={path}>{locale}</a>
49+
{/each}
50+
</nav>
2951
</div>
3052
</header>
3153

@@ -36,7 +58,7 @@
3658
}
3759
3860
.corner {
39-
width: 3em;
61+
display: flex;
4062
height: 3em;
4163
}
4264
@@ -46,6 +68,23 @@
4668
justify-content: center;
4769
width: 100%;
4870
height: 100%;
71+
text-transform: uppercase;
72+
}
73+
74+
.corner nav a {
75+
position: relative;
76+
}
77+
78+
.corner a.active::before {
79+
--size: 6px;
80+
content: '';
81+
width: 0;
82+
height: 0;
83+
position: absolute;
84+
top: 0;
85+
left: calc(50% - var(--size));
86+
border: var(--size) solid transparent;
87+
border-top: var(--size) solid var(--accent-color);
4988
}
5089
5190
.corner img {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { derived } from 'svelte/store';
2+
import { page } from '$app/stores';
3+
import { alternates } from '$app/navigation';
4+
5+
import locales from '../../locales';
6+
7+
export const defaultLocale = locales[0];
8+
9+
export const locale = derived(
10+
page,
11+
(page) => page.path.match(/^\/([a-z]{2})(\/|$)/)?.[1] || defaultLocale
12+
);
13+
14+
export const localizedPaths = derived(page, (page) => (path: string): Record<string, string> =>
15+
alternates(path)?.reduce((result, alt) => {
16+
result[alt.match(/^\/([a-z]{2})(\/|$)/)?.[1] || defaultLocale] = alt;
17+
return result;
18+
}, {})
19+
);
20+
21+
export const l = derived(
22+
[localizedPaths, locale],
23+
([localizedPaths, locale]) => (path: string): string => localizedPaths(path)?.[locale] || path
24+
);
25+
26+
export { l as localize };

packages/create-svelte/templates/default/svelte.config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import preprocess from 'svelte-preprocess';
2+
import { localizeRoutes } from './i18n.config.js';
23

34
const adapter = process.env.ADAPTER;
45
const options = JSON.parse(process.env.OPTIONS || '{}');
@@ -11,7 +12,9 @@ const config = {
1112

1213
kit: {
1314
// hydrate the <div id="svelte"> element in src/app.html
14-
target: '#svelte'
15+
target: '#svelte',
16+
17+
alternateRoutes: localizeRoutes
1518
}
1619
};
1720

0 commit comments

Comments
 (0)