Skip to content

Commit 3545d69

Browse files
committed
Added i18n routes to default template demonstrating alternate pages
1 parent eba0281 commit 3545d69

File tree

6 files changed

+115
-7
lines changed

6 files changed

+115
-7
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import locales from './src/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+
}

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

Lines changed: 43 additions & 6 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.url.pathname);
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,12 +28,14 @@
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.url.pathname === '/'}><a sveltekit:prefetch href="/">Home</a></li>
19-
<li class:active={$page.url.pathname === '/about'}>
20-
<a sveltekit:prefetch href="/about">About</a>
31+
<li class:active={$page.url.pathname === $l('/')}>
32+
<a sveltekit:prefetch href={$l('/')}>Home</a>
33+
</li>
34+
<li class:active={$page.url.pathname === $l('/about')}>
35+
<a sveltekit:prefetch href={$l('/about')}>About</a>
2136
</li>
22-
<li class:active={$page.url.pathname === '/todos'}>
23-
<a sveltekit:prefetch href="/todos">Todos</a>
37+
<li class:active={$page.url.pathname === $l('/todos')}>
38+
<a sveltekit:prefetch href={$l('/todos')}>Todos</a>
2439
</li>
2540
</ul>
2641
<svg viewBox="0 0 2 3" aria-hidden="true">
@@ -30,6 +45,11 @@
3045

3146
<div class="corner">
3247
<!-- TODO put something else here? github link? -->
48+
<nav>
49+
{#each Object.entries(alternatePaths) as [locale, path]}
50+
<a class:active={$currentLocale === locale} href={path}>{locale}</a>
51+
{/each}
52+
</nav>
3353
</div>
3454
</header>
3555

@@ -40,7 +60,7 @@
4060
}
4161
4262
.corner {
43-
width: 3em;
63+
display: flex;
4464
height: 3em;
4565
}
4666
@@ -50,6 +70,23 @@
5070
justify-content: center;
5171
width: 100%;
5272
height: 100%;
73+
text-transform: uppercase;
74+
}
75+
76+
.corner nav a {
77+
position: relative;
78+
}
79+
80+
.corner a.active::before {
81+
--size: 6px;
82+
content: '';
83+
width: 0;
84+
height: 0;
85+
position: absolute;
86+
top: 0;
87+
left: calc(50% - var(--size));
88+
border: var(--size) solid transparent;
89+
border-top: var(--size) solid var(--accent-color);
5390
}
5491
5592
.corner img {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { derived, readable } 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.url.pathname.match(/^\/([a-z]{2})(\/|$)/)?.[1] || defaultLocale
12+
);
13+
14+
export const localizedPaths = readable(
15+
(path: string): Record<string, string> =>
16+
alternates(path)?.reduce((result, alt) => {
17+
result[alt.match(/^\/([a-z]{2})(\/|$)/)?.[1] || defaultLocale] = alt;
18+
return result;
19+
}, {})
20+
);
21+
22+
export const l = derived(
23+
[localizedPaths, locale],
24+
([localizedPaths, locale]) =>
25+
(path: string): string =>
26+
localizedPaths(path)?.[locale] || path
27+
);
28+
29+
export { l as localize };
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/svelte.config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import adapter from '@sveltejs/adapter-auto';
22
import preprocess from 'svelte-preprocess';
3+
import { localizeRoutes } from './i18n.config.js';
34

45
/** @type {import('@sveltejs/kit').Config} */
56
const config = {
@@ -16,7 +17,9 @@ const config = {
1617
// Override http methods in the Todo forms
1718
methodOverride: {
1819
allowed: ['PATCH', 'DELETE']
19-
}
20+
},
21+
22+
alternateRoutes: localizeRoutes
2023
}
2124
};
2225

packages/kit/src/core/create_manifest_data/index.spec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ test('disallows rest parameters inside segments', () => {
225225

226226
assert.equal(routes, [
227227
{
228+
id: '2',
228229
type: 'page',
229230
segments: [
230231
{

0 commit comments

Comments
 (0)