Migrate to sveltekit #26
18 changed files with 126 additions and 75 deletions
21
.gitignore
vendored
21
.gitignore
vendored
|
@ -23,3 +23,24 @@ dist-ssr
|
|||
*.sln
|
||||
*.sw?
|
||||
/.vscode
|
||||
.DS_Store
|
||||
node_modules
|
||||
dist
|
||||
test-results/
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
vite.config.js.timestamp-*
|
||||
/packages/create-svelte/template/CHANGELOG.md
|
||||
/packages/package/test/**/package
|
||||
/documentation/types.js
|
||||
.env
|
||||
.vercel_build_output
|
||||
.svelte-kit
|
||||
.cloudflare
|
||||
.pnpm-debug.log
|
||||
.netlify
|
||||
.turbo
|
||||
.vercel
|
||||
.test-tmp
|
||||
symlink-from
|
||||
.idea/
|
||||
|
|
|
@ -9,7 +9,7 @@ export const nodes = [
|
|||
() => import('./nodes/5')
|
||||
];
|
||||
|
||||
export const server_loads = [];
|
||||
export const server_loads = [0];
|
||||
|
||||
export const dictionary = {
|
||||
"/": [2],
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
import * as universal from "../../../../src/routes/+layout.js";
|
||||
export { universal };
|
||||
export { default as component } from "../../../../src/routes/+layout.svelte";
|
|
@ -21,7 +21,7 @@ export const options = {
|
|||
app: ({ head, body, assets, nonce, env }) => "<!doctype html>\n<html lang=\"en\">\n <head>\n <style>\n :root {\n font-family: Inter, Avenir, Helvetica, Arial, sans-serif;\n font-size: 16px;\n line-height: 24px;\n font-weight: 400;\n font-synthesis: none;\n text-rendering: optimizeLegibility;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n -webkit-text-size-adjust: 100%;\n }\n\n * {\n box-sizing: border-box;\n }\n\n body {\n display: flex;\n justify-content: center;\n flex-direction: column;\n margin: 0;\n width: 100%;\n height: 100%;\n }\n\n #app {\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n background-color: #f2f6f5;\n z-index: 10;\n }\n\n input[type='submit'] {\n width: 100%;\n font-size: 20px;\n margin-top: 20px;\n background-color: #05345f;\n font-weight: 700;\n color: white;\n padding: 10px;\n -webkit-appearance: none;\n border-radius: 0;\n }\n\n input[type='submit']:hover {\n cursor: pointer;\n background-color: black;\n color: white;\n }\n\n body a {\n text-decoration: none;\n color: #06345f;\n border-bottom: 3px solid #06345f;\n }\n\n body a:hover {\n background-color: #06345f;\n color: #ffffff;\n }\n\n :is(h1, h2, h3, h4, h5, h6) {\n color: #06345f;\n }\n\n strong {\n color: #06345f;\n }\n\n ul li::marker {\n color: #06345f;\n }\n </style>\n <meta charset=\"utf-8\" />\n <link rel=\"icon\" href=\"" + assets + "/favicon.png\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n " + head + "\n </head>\n <body data-sveltekit-preload-data=\"hover\">\n <div style=\"display: contents\">" + body + "</div>\n </body>\n</html>\n",
|
||||
error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
|
||||
},
|
||||
version_hash: "lnkeyd"
|
||||
version_hash: "1f4q059"
|
||||
};
|
||||
|
||||
export async function get_hooks() {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"/": [
|
||||
"src/routes/+layout.js",
|
||||
"src/routes/+layout.js"
|
||||
"src/routes/+layout.server.js",
|
||||
"src/routes/+layout.server.js"
|
||||
],
|
||||
"/about": [
|
||||
"src/routes/+layout.js"
|
||||
"src/routes/+layout.server.js"
|
||||
],
|
||||
"/donate": [
|
||||
"src/routes/+layout.js"
|
||||
"src/routes/+layout.server.js"
|
||||
],
|
||||
"/viewer": [
|
||||
"src/routes/+layout.js"
|
||||
"src/routes/+layout.server.js"
|
||||
]
|
||||
}
|
12
.svelte-kit/types/src/routes/$types.d.ts
vendored
12
.svelte-kit/types/src/routes/$types.d.ts
vendored
|
@ -14,13 +14,15 @@ export type Snapshot<T = any> = Kit.Snapshot<T>;
|
|||
type PageParentData = EnsureDefined<LayoutData>;
|
||||
type LayoutRouteId = RouteId | "/" | "/about" | "/donate" | "/viewer" | null
|
||||
type LayoutParams = RouteParams & { }
|
||||
type LayoutServerParentData = EnsureDefined<{}>;
|
||||
type LayoutParentData = EnsureDefined<{}>;
|
||||
|
||||
export type PageServerData = null;
|
||||
export type PageData = Expand<PageParentData>;
|
||||
export type PageProps = { data: PageData }
|
||||
export type LayoutServerData = null;
|
||||
export type LayoutLoad<OutputData extends OutputDataShape<LayoutParentData> = OutputDataShape<LayoutParentData>> = Kit.Load<LayoutParams, LayoutServerData, LayoutParentData, OutputData, LayoutRouteId>;
|
||||
export type LayoutLoadEvent = Parameters<LayoutLoad>[0];
|
||||
export type LayoutData = Expand<Omit<LayoutParentData, keyof Kit.LoadProperties<Awaited<ReturnType<typeof import('./proxy+layout.js').load>>>> & OptionalUnion<EnsureDefined<Kit.LoadProperties<Awaited<ReturnType<typeof import('./proxy+layout.js').load>>>>>>;
|
||||
export type LayoutProps = { data: LayoutData; children: import("svelte").Snippet }
|
||||
export type LayoutServerLoad<OutputData extends OutputDataShape<LayoutServerParentData> = OutputDataShape<LayoutServerParentData>> = Kit.ServerLoad<LayoutParams, LayoutServerParentData, OutputData, LayoutRouteId>;
|
||||
export type LayoutServerLoadEvent = Parameters<LayoutServerLoad>[0];
|
||||
export type LayoutServerData = Expand<OptionalUnion<EnsureDefined<Kit.LoadProperties<Awaited<ReturnType<typeof import('./proxy+layout.server.js').load>>>>>>;
|
||||
export type LayoutData = Expand<Omit<LayoutParentData, keyof LayoutServerData> & EnsureDefined<LayoutServerData>>;
|
||||
export type LayoutProps = { data: LayoutData; children: import("svelte").Snippet }
|
||||
export type RequestEvent = Kit.RequestEvent<RouteParams, RouteId>;
|
|
@ -1,17 +0,0 @@
|
|||
// @ts-nocheck
|
||||
import { loadTranslations } from '$lib/translations';
|
||||
|
||||
/** */
|
||||
export const load = async () => {
|
||||
const initLocale = primaryLanguage(navigator.language) || 'en';
|
||||
|
||||
// TODO: Fix the undefined location issue
|
||||
await loadTranslations(initLocale);
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
const primaryLanguage = (/** @type {string} */ locale) => {
|
||||
if (!locale) return '';
|
||||
return locale.split('-')[0];
|
||||
};
|
7
package-lock.json
generated
7
package-lock.json
generated
|
@ -8,6 +8,7 @@
|
|||
"name": "embroidery-viewer",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"accept-language-parser": "^1.5.0",
|
||||
"sveltekit-i18n": "^2.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1165,6 +1166,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/accept-language-parser": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/accept-language-parser/-/accept-language-parser-1.5.0.tgz",
|
||||
"integrity": "sha512-QhyTbMLYo0BBGg1aWbeMG4ekWtds/31BrEU+DONOg/7ax23vxpL03Pb7/zBmha2v7vdD3AyzZVWBVGEZxKOXWw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
"vite": "^6.2.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"accept-language-parser": "^1.5.0",
|
||||
"sveltekit-i18n": "^2.4.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { t, locale, locales } from '$lib/translations';
|
||||
import { t, locale, locales, SUPPORTED_LOCALES } from '$lib/translations';
|
||||
import logo from '$lib/assets/logo.webp';
|
||||
import MediaQuery from './MediaQuery.svelte';
|
||||
|
||||
|
@ -10,7 +10,10 @@
|
|||
};
|
||||
|
||||
const onSwitchToOppositeLang = () => {
|
||||
$locale = $locale === 'en' ? 'pt' : 'en';
|
||||
$locale =
|
||||
$locale === SUPPORTED_LOCALES.EN_US
|
||||
? SUPPORTED_LOCALES.PT_BR
|
||||
: SUPPORTED_LOCALES.EN_US;
|
||||
};
|
||||
|
||||
let isMenuOpen = false;
|
||||
|
@ -59,7 +62,7 @@
|
|||
</nav>
|
||||
|
||||
<a
|
||||
class="common-switch {$locale === 'en'
|
||||
class="common-switch {$locale === SUPPORTED_LOCALES.EN_US
|
||||
? 'portuguese-switch'
|
||||
: 'english-switch'}"
|
||||
href="#"
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
// place files you want to import through the `$lib` alias in this folder.
|
|
@ -1,22 +1,33 @@
|
|||
import i18n from 'sveltekit-i18n';
|
||||
import lang from './lang.json';
|
||||
|
||||
/**
|
||||
* A frozen object mapping locale identifiers to their respective locale codes.
|
||||
*
|
||||
* These values represent the supported languages in the application.
|
||||
* Used for validating user preferences and loading the correct translations.
|
||||
*
|
||||
* @readonly
|
||||
* @enum {string}
|
||||
*/
|
||||
export const SUPPORTED_LOCALES = Object.freeze({
|
||||
EN_US: 'en-US',
|
||||
PT_BR: 'pt-BR',
|
||||
});
|
||||
|
||||
/** @type {import('sveltekit-i18n').Config} */
|
||||
const config = {
|
||||
translations: {
|
||||
en: { lang },
|
||||
pt: { lang },
|
||||
},
|
||||
initLocale: navigator.language,
|
||||
fallbackLocale: SUPPORTED_LOCALES.PT_BR,
|
||||
loaders: [
|
||||
{
|
||||
locale: 'en',
|
||||
locale: SUPPORTED_LOCALES.EN_US,
|
||||
key: 'header',
|
||||
loader: async () => (await import('./en/header.json')).default,
|
||||
loader: async () => (await import('./en-US/header.json')).default,
|
||||
},
|
||||
{
|
||||
locale: 'pt',
|
||||
locale: SUPPORTED_LOCALES.PT_BR,
|
||||
key: 'header',
|
||||
loader: async () => (await import('./pt/header.json')).default,
|
||||
loader: async () => (await import('./pt-BR/header.json')).default,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -25,17 +36,8 @@ export const { t, locale, locales, loading, loadTranslations } = new i18n(
|
|||
config,
|
||||
);
|
||||
|
||||
// Save to localStorage on change
|
||||
locale.subscribe(($locale) => {
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
localStorage.setItem('locale', $locale);
|
||||
if (typeof document !== 'undefined') {
|
||||
document.cookie = `locale=${$locale}; path=/; SameSite=Strict;`;
|
||||
}
|
||||
});
|
||||
|
||||
// Load from localStorage on initialization
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
const savedLocale = localStorage.getItem('locale');
|
||||
if (savedLocale && savedLocale !== 'null') {
|
||||
locale.set(savedLocale);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"en": "English",
|
||||
"pt": "Português"
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { loadTranslations } from '$lib/translations';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Load} */
|
||||
export const load = async () => {
|
||||
const initLocale = primaryLanguage(navigator.language) || 'en';
|
||||
|
||||
// TODO: Fix the undefined location issue
|
||||
await loadTranslations(initLocale);
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
const primaryLanguage = (/** @type {string} */ locale) => {
|
||||
if (!locale) return '';
|
||||
return locale.split('-')[0];
|
||||
};
|
51
src/routes/+layout.server.js
Normal file
51
src/routes/+layout.server.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { parse } from 'accept-language-parser';
|
||||
import { loadTranslations } from '$lib/translations';
|
||||
import { SUPPORTED_LOCALES } from '$lib/translations';
|
||||
|
||||
/**
|
||||
* A set of all supported locale codes, used to validate and match against
|
||||
* user preferences from cookies or Accept-Language headers. We're using a
|
||||
* Set for better performance in lookup.
|
||||
*
|
||||
* Example values: "en-US", "pt-BR"
|
||||
* @type {Set<string>}
|
||||
*/
|
||||
const SUPPORTED_LOCALE_SET = new Set(Object.values(SUPPORTED_LOCALES));
|
||||
|
||||
/**
|
||||
* Returns a valid locale from cookies, or null if not valid/found.
|
||||
* @param {{ get: (cookies: string) => any; }} cookies
|
||||
*/
|
||||
function localeFromCookies(cookies) {
|
||||
const locale = cookies.get('locale');
|
||||
return locale && SUPPORTED_LOCALE_SET.has(locale) ? locale : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the Accept-Language header and returns the best matching locale.
|
||||
* @param {string | null | undefined} header
|
||||
*/
|
||||
function localeFromHeader(header) {
|
||||
if (!header) return null;
|
||||
|
||||
const parsedLanguages = parse(header);
|
||||
for (const { code, region } of parsedLanguages) {
|
||||
const locale = region ? `${code}-${region}` : code;
|
||||
if (SUPPORTED_LOCALE_SET.has(locale)) {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @type {import('@sveltejs/kit').ServerLoad}*/
|
||||
export async function load({ request, cookies }) {
|
||||
const cookieLocale = localeFromCookies(cookies);
|
||||
const headerLocale = localeFromHeader(request.headers.get('accept-language'));
|
||||
const language = cookieLocale || headerLocale || SUPPORTED_LOCALES.EN_US;
|
||||
|
||||
await loadTranslations(language);
|
||||
|
||||
return { language };
|
||||
}
|
|
@ -1,5 +1,9 @@
|
|||
<script>
|
||||
import { locale } from '$lib/translations';
|
||||
import Header from '$lib/components/Header.svelte';
|
||||
export let data;
|
||||
|
||||
$: locale.set(data.language);
|
||||
</script>
|
||||
|
||||
<Header />
|
||||
|
|
Loading…
Add table
Reference in a new issue