initial stuff

This commit is contained in:
Henri
2025-11-21 08:15:07 +02:00
parent a38a367ac5
commit 8c18827dc5
33 changed files with 522 additions and 148 deletions

35
src/lib/i18n.js Normal file
View File

@@ -0,0 +1,35 @@
import { writable } from 'svelte/store';
// Load saved language or default to 'est'
const savedLang = typeof window !== 'undefined'
? localStorage.getItem('language') || 'est'
: 'est';
// Store for current language
export const currentLang = writable(savedLang);
// Store for translations
export const text = writable({});
// Load translations for a specific language
async function loadTranslations(lang) {
try {
const response = await fetch(`/locales/${lang}.json`);
const data = await response.json();
text.set(data);
} catch (error) {
console.error(`Failed to load translations for ${lang}:`, error);
}
}
// Initialize translations
loadTranslations(savedLang);
// Function to switch language
export function switchLang(lang) {
currentLang.set(lang);
loadTranslations(lang);
if (typeof window !== 'undefined') {
localStorage.setItem('language', lang);
}
}

4
src/lib/index.js Normal file
View File

@@ -0,0 +1,4 @@
export { navigate, goBack, reload, getPath, getQuery } from './router/router.js';
export { default as Router } from './router/Router.svelte';
export { currentLang, text, switchLang } from './i18n.js';

View File

@@ -2,6 +2,11 @@
<!-- unless the router is broken 👉👈 -->
<script>
export function routeTo(path) {
window.history.pushState({}, "", path);
window.dispatchEvent(new PopStateEvent("popstate"));
}
let { routes } = $props();
let currentPath = $state(window.location.pathname);

44
src/lib/router/router.js Normal file
View File

@@ -0,0 +1,44 @@
/**
* Navigate to a path (internal or external)
* @param {string} path - The path or URL to navigate to
* @param {boolean} external - Whether this is an external link (default: false)
*/
export function navigate(path, external = false) {
if (external) {
window.location.href = path;
} else {
window.history.pushState({}, "", path);
window.dispatchEvent(new PopStateEvent('popstate'));
}
}
/**
* Go back in browser history
*/
export function goBack() {
window.history.back();
}
/**
* Reload the current page
*/
export function reload() {
window.location.reload();
}
/**
* Get the current pathname
* @returns {string} Current path
*/
export function getPath() {
return window.location.pathname;
}
/**
* Get URL query parameters as an object
* @returns {Object} Query parameters
*/
export function getQuery() {
const params = new URLSearchParams(window.location.search);
return Object.fromEntries(params.entries());
}

View File

@@ -1,22 +0,0 @@
// THEME STORE for LIGHT / DARK mode
import { writable } from 'svelte/store'
const init = (() => {
try {
const stored = localStorage.getItem('theme')
if (stored === 'light' || stored === 'dark') return stored
} catch (e) { }
return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'
})()
export const theme = writable(init)
theme.subscribe(value => {
try { localStorage.setItem('theme', value) } catch (e) { }
document.documentElement.dataset.theme = value
})
export function toggle() {
theme.update(t => t === 'dark' ? 'light' : 'dark')
}