Skip to content

Commit

Permalink
Added i18n routes to default template demonstrating alternate pages
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Zerelles authored and pzerelles committed Jul 27, 2021
1 parent bc1433f commit 6ab0029
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 5 deletions.
37 changes: 37 additions & 0 deletions packages/create-svelte/templates/default/i18n.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import locales from './locales.js';

export const defaultLocale = locales[0];

/** @typedef {{
* content: string;
* dynamic: boolean;
* spread: boolean;
* }} Part */

/**
* Create localized routes prefixed with locale
* @param {Part[][]} segments
* @param {'page' | 'endpoint'} type
* @returns {Part[][][]}
*/
export function localizeRoutes(segments, type) {
if (type === 'endpoint') return [segments];
return locales.map((locale) =>
locale === defaultLocale
? segments
: [
[{ content: locale, dynamic: false, spread: false }],
...segments.map((segment) => segment.map((part) => translate(part)))
]
);
}

/**
* Translate part of a route segment
* @param {Part} part
* @returns {Part}
*/
function translate(part) {
if (part.content === 'about') return { ...part, content: 'ueber' };
return part;
}
1 change: 1 addition & 0 deletions packages/create-svelte/templates/default/locales.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default ['en', 'de'];
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
<script lang="ts">
import { page } from '$app/stores';
import logo from './svelte-logo.svg';
import { l, localizedPaths, locale as currentLocale, defaultLocale } from '$lib/i18n';
$: alternatePaths = $localizedPaths($page.path) || {};
$: defaultPath = alternatePaths[defaultLocale];
</script>

<svelte:head>
{#if defaultPath}
<link rel="alternate" hreflang="x-default" href={defaultPath} />
{/if}
{#each Object.entries(alternatePaths) as [locale, path]}
<link rel="alternate" hreflang={locale} href={path} />
{/each}
</svelte:head>

<header>
<div class="corner">
<a href="https://kit.svelte.dev">
Expand All @@ -15,9 +28,13 @@
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
</svg>
<ul>
<li class:active={$page.path === '/'}><a sveltekit:prefetch href="/">Home</a></li>
<li class:active={$page.path === '/about'}><a sveltekit:prefetch href="/about">About</a></li>
<li class:active={$page.path === '/todos'}><a sveltekit:prefetch href="/todos">Todos</a></li>
<li class:active={$page.path === $l('/')}><a sveltekit:prefetch href={$l('/')}>Home</a></li>
<li class:active={$page.path === $l('/about')}>
<a sveltekit:prefetch href={$l('/about')}>About</a>
</li>
<li class:active={$page.path === $l('/todos')}>
<a sveltekit:prefetch href={$l('/todos')}>Todos</a>
</li>
</ul>
<svg viewBox="0 0 2 3" aria-hidden="true">
<path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" />
Expand All @@ -26,6 +43,11 @@

<div class="corner">
<!-- TODO put something else here? github link? -->
<nav>
{#each Object.entries(alternatePaths) as [locale, path]}
<a class:active={$currentLocale === locale} href={path}>{locale}</a>
{/each}
</nav>
</div>
</header>

Expand All @@ -36,7 +58,7 @@
}
.corner {
width: 3em;
display: flex;
height: 3em;
}
Expand All @@ -46,6 +68,23 @@
justify-content: center;
width: 100%;
height: 100%;
text-transform: uppercase;
}
.corner nav a {
position: relative;
}
.corner a.active::before {
--size: 6px;
content: '';
width: 0;
height: 0;
position: absolute;
top: 0;
left: calc(50% - var(--size));
border: var(--size) solid transparent;
border-top: var(--size) solid var(--accent-color);
}
.corner img {
Expand Down
26 changes: 26 additions & 0 deletions packages/create-svelte/templates/default/src/lib/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { derived } from 'svelte/store';
import { page } from '$app/stores';
import { alternates } from '$app/navigation';

import locales from '../../locales';

export const defaultLocale = locales[0];

export const locale = derived(
page,
(page) => page.path.match(/^\/([a-z]{2})(\/|$)/)?.[1] || defaultLocale
);

export const localizedPaths = derived(page, (page) => (path: string): Record<string, string> =>
alternates(path)?.reduce((result, alt) => {
result[alt.match(/^\/([a-z]{2})(\/|$)/)?.[1] || defaultLocale] = alt;
return result;
}, {})
);

export const l = derived(
[localizedPaths, locale],
([localizedPaths, locale]) => (path: string): string => localizedPaths(path)?.[locale] || path
);

export { l as localize };
5 changes: 4 additions & 1 deletion packages/create-svelte/templates/default/svelte.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import preprocess from 'svelte-preprocess';
import { localizeRoutes } from './i18n.config.js';

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

kit: {
// hydrate the <div id="svelte"> element in src/app.html
target: '#svelte'
target: '#svelte',

alternateRoutes: localizeRoutes
}
};

Expand Down

0 comments on commit 6ab0029

Please sign in to comment.