20 Commits

Author SHA1 Message Date
d160e6d1ca 🐛 Fix language not switching on dynamic pages
All checks were successful
Build and deploy website / build (push) Successful in 34s
2025-07-28 18:17:18 +00:00
3840766ad5 Fixed language not switching 2025-07-28 18:17:18 +00:00
e06ef027fd Update TODO
Signed-off-by: Martin Berg Alstad <git@martials.no>
2025-07-28 18:17:18 +00:00
e5a95e0c97 Start updating paraglide to v2 2025-07-28 18:17:18 +00:00
c9cb20cd38 🔥 Remove prettier 2025-07-28 18:17:18 +00:00
a77266b683 Update git domain 2025-07-28 18:17:18 +00:00
15440bb912 🎨 Fix lint errors using Biome 2025-07-28 18:17:18 +00:00
fafc48cfce 🎨 Format using Biome 2025-07-28 18:17:18 +00:00
cae5e408bd Adde Biome formatter and linter 2025-07-28 18:17:18 +00:00
869074dd89 ❄️ Add Nix shell 2025-07-28 18:17:18 +00:00
1892d38d18 📦 Update dependencies 2025-07-28 18:17:18 +00:00
d5ca576068 ✍️ Update TODO.md 2025-07-28 18:17:18 +00:00
b1061e56c6 🐛 Fix trailing slash 2025-07-28 18:17:18 +00:00
1fa2667deb 👷 Merge into single docker compose file
All checks were successful
Build and deploy website / build (push) Successful in 22s
2025-07-03 18:54:54 +02:00
19d78991c8 👷 Update ref keys and master to develop on develop step
All checks were successful
Build and deploy website / build (push) Successful in 1m3s
2025-07-03 18:39:42 +02:00
1dadaabe94 👷 Staging from develop branch
All checks were successful
Build and deploy website / build (push) Successful in 2s
2025-07-03 18:34:49 +02:00
dc4d564059 Breadcrumbs with navigation for mobile
All checks were successful
Build and deploy website / build (push) Successful in 33s
2025-03-16 21:32:11 +01:00
05ef06f95c Breadcrumbs with navigation
All checks were successful
Build and deploy website / build (push) Successful in 38s
2025-03-15 15:34:24 +01:00
097850267c Homelab and raspberry pi uses
All checks were successful
Build and deploy website / build (push) Successful in 1m0s
2025-03-10 21:44:20 +01:00
9a82eba757 📦 Updated Astro to v5.4 and DaisyUI to v5 2025-03-01 10:04:48 +01:00
32 changed files with 1678 additions and 2056 deletions

2
.env
View File

@ -1,3 +1,3 @@
DOMAIN="martials.no"
GIT_URL=https://git.$DOMAIN
GIT_URL=https://code.$DOMAIN
STATUS_URL="https://status.$DOMAIN/status/home"

View File

@ -4,9 +4,7 @@ on:
push:
branches:
- master
pull_request:
branches:
- master
- develop
jobs:
build:
@ -15,5 +13,9 @@ jobs:
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Run docker-compose
run: docker compose up -d --build
- name: Build production
run: docker compose up -d --build prod
if: gitea.ref == 'refs/heads/master'
- name: Build develop
run: docker compose up -d --build dev
if: gitea.ref == 'refs/heads/develop'

14
TODO.md
View File

@ -3,17 +3,23 @@
- [ ] License
## Code
- [ ] Nix Shell
- [x] Nix Shell
- [ ] Analytics
- [ ] Organize code better
- [ ] Type slug of project
## CI/CD
- [x] Staging environment
- [x] Deploy to staging environment on push to develop
- [x] Deploy to production environment on push to master
- [ ] Staging environment .env file
## SEO
- [ ] Meta tags on each page
## Layout
- [ ] Dark mode toggle
- [ ] Navigate using pathname / breadcrumbs
- [x] Navigate using pathname / breadcrumbs
- [ ] Better style for \<code /> blocks
## Accessibility
@ -51,8 +57,8 @@
- [ ] List of all slashes
## ~/uses
- [ ] Homelab uses
- [ ] Raspberry PI uses
- [x] Homelab uses
- [x] Raspberry PI uses
- [ ] Hardware anchor
## ~/certifications

View File

@ -1,6 +1,5 @@
// @ts-check
import { defineConfig, envField } from "astro/config"
import paraglide from "@inlang/paraglide-astro"
import tailwindcss from "@tailwindcss/vite"
import sitemap from "@astrojs/sitemap"
import svelte from "@astrojs/svelte"
@ -9,6 +8,7 @@ import mdx from "@astrojs/mdx"
import icon from "astro-icon"
import { loadEnv } from "vite"
import { paraglideVitePlugin } from "@inlang/paraglide-js"
const { URL } = process.env.NODE_ENV
? loadEnv(process.env.NODE_ENV, process.cwd(), "")
@ -20,35 +20,37 @@ export default defineConfig({
output: "server",
i18n: {
defaultLocale: "nb",
locales: ["nb", "en"],
locales: ["nb", "en"]
},
integrations: [
sitemap(),
mdx(),
svelte(),
icon(),
paraglide({
project: "./project.inlang",
outdir: "./src/paraglide",
}),
icon()
],
adapter: node({
mode: "standalone",
mode: "standalone"
}),
vite: {
plugins: [tailwindcss()],
plugins: [
tailwindcss(),
paraglideVitePlugin({
project: "./project.inlang",
outdir: "./src/paraglide"
})
]
},
markdown: {
shikiConfig: {
theme: "catppuccin-mocha",
},
theme: "catppuccin-mocha"
}
},
env: {
schema: {
DOMAIN: envField.string({ context: "client", access: "public" }),
URL: envField.string({ context: "client", access: "public" }),
GIT_URL: envField.string({ context: "client", access: "public" }),
STATUS_URL: envField.string({ context: "client", access: "public" }),
},
},
STATUS_URL: envField.string({ context: "client", access: "public" })
}
}
})

57
biome.jsonc Normal file
View File

@ -0,0 +1,57 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": ["./src/paraglide"],
"include": ["./src/**"]
},
"formatter": {
"enabled": true,
"indentStyle": "space"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded"
}
},
"overrides": [
{
"include": ["*.astro"],
"linter": {
"rules": {
"style": {
"useConst": "off",
"useImportType": "off"
}
}
}
},
{
"include": ["*.svelte"],
"linter": {
"rules": {
"style": {
"useConst": "off",
"useImportType": "off"
}
}
}
}
]
}

View File

@ -1,9 +1,20 @@
services:
web:
container_name: martials.no
prod:
hostname: martials.no
container_name: "martials.no"
restart: always
build:
context: .
dockerfile: Dockerfile
ports:
- "4321:4321"
dev:
hostname: dev.martials.no
container_name: "dev.martials.no"
restart: always
build:
context: .
dockerfile: Dockerfile
ports:
- "4322:4321"

27
flake.lock generated Normal file
View File

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1751211869,
"narHash": "sha256-1Cu92i1KSPbhPCKxoiVG5qnoRiKTgR5CcGSRyLpOd7Y=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "b43c397f6c213918d6cfe6e3550abfe79b5d1c51",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

37
flake.nix Normal file
View File

@ -0,0 +1,37 @@
{
description = "martials.no Development environment";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
};
outputs = { nixpkgs, ... }:
let
system = "x86_64-linux";
in
{
devShells.${system}.default =
let
pkgs = import nixpkgs {
inherit system;
};
in
pkgs.mkShell {
packages = with pkgs; [
git
] ++ [
# Node
nodejs_22
pnpm
] ++ [
nodePackages.prettier
biome
];
shellHook = ''
pnpm install
fish
'';
};
};
}

View File

@ -10,49 +10,31 @@
"astro": "astro",
"type-check": "astro check",
"postinstall": "paraglide-js compile --project ./project.inlang --outdir ./src/paraglide",
"format": "prettier --write \"./src/**/*.{js,mjs,ts,astro,svelte,css,md,json}\"",
"format": "biome format --write .",
"lint": "biome lint --write .",
"lint:fix": "biome check --write .",
"watch-messages": "paraglide-js compile --watch --project ./project.inlang --outdir ./src/paraglide"
},
"dependencies": {
"@astrojs/check": "^0.9.4",
"@astrojs/mdx": "^4.0.8",
"@astrojs/node": "9.1.1",
"@astrojs/sitemap": "^3.2.1",
"@astrojs/svelte": "^7.0.4",
"@iconify-json/pajamas": "^1.2.5",
"@inlang/paraglide-astro": "^0.3.5",
"@inlang/paraglide-js": "1.11.8",
"@astrojs/mdx": "^4.3.0",
"@astrojs/node": "9.2.2",
"@astrojs/sitemap": "^3.4.1",
"@astrojs/svelte": "^7.1.0",
"@iconify-json/pajamas": "^1.2.11",
"@inlang/paraglide-js": "2.1.0",
"@tailwindcss/typography": "^0.5.16",
"@tailwindcss/vite": "^4.0.9",
"astro": "^5.3.1",
"@tailwindcss/vite": "^4.1.11",
"astro": "^5.10.2",
"astro-icon": "^1.1.5",
"dayjs": "^1.11.13",
"sharp": "^0.33.5",
"svelte": "^5.20.4",
"tailwindcss": "^4.0.9",
"typescript": "^5.7.3"
"sharp": "^0.34.2",
"svelte": "^5.34.9",
"tailwindcss": "^4.1.11",
"typescript": "^5.8.3"
},
"devDependencies": {
"daisyui": "^5.0.0-beta.8",
"prettier": "^3.5.2",
"prettier-plugin-astro": "^0.14.1",
"prettier-plugin-svelte": "^3.3.3",
"vite": "^6.2.0"
},
"prettier": {
"semi": false,
"singleQuote": false,
"plugins": [
"prettier-plugin-astro",
"prettier-plugin-svelte"
],
"overrides": [
{
"files": "**/*.astro",
"options": {
"parser": "astro"
}
}
]
"daisyui": "^5.0.43",
"vite": "^7.0.0"
}
}

3062
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,15 @@
{
"$schema": "https://inlang.com/schema/project-settings",
"sourceLanguageTag": "nb",
"languageTags": ["nb", "en"],
"baseLocale": "nb",
"locales": [
"nb",
"en"
],
"modules": [
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-empty-pattern@latest/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-missing-translation@latest/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/message-lint-rule-without-source@latest/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@latest/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@latest/dist/index.js"
"https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js"
],
"plugin.inlang.messageFormat": {
"pathPattern": "./messages/{languageTag}.json"
"pathPattern": "./messages/{locale}.json"
}
}

View File

@ -0,0 +1,39 @@
---
import { type NavLink } from "@/utils/linking"
import LocaleLink from "@/components/links/LocaleLink.astro"
import { deLocalizeHref } from "@/paraglide/runtime.js"
const pathname = deLocalizeHref(Astro.originPathname)
let paths: string[]
if (pathname === "/") {
paths = ["~"]
} else {
paths = ["~", ...pathname.split("/").filter(x => x)]
}
function getLink(path: string): NavLink {
switch (path) {
case "~":
return "/"
default:
return `/${path}` as NavLink
}
}
---
<div>
{
paths.map((path, index) => (
<span>
{ index != paths.length - 1 ? (
<span>
<LocaleLink to={ getLink(path) }>{ path }</LocaleLink>/
</span>
) : (
path
) }
</span>
))
}
</div>

View File

@ -2,11 +2,12 @@
import GiteaLink from "./links/GiteaLink.astro"
import PajamasIcon from "./icons/PajamasIcon.astro"
import ExternalLink from "./links/ExternalLink.astro"
import LanguageButtonGroup from "./LanguageButtonGroup.astro"
import LanguageButtonGroup from "./LanguageButtonGroup.svelte"
import { GIT_URL, STATUS_URL } from "astro:env/client"
import * as m from "@/paraglide/messages"
const giteaLink = `${GIT_URL}/martials/martials.no`
const pathname = Astro.url.pathname
---
<div class="divider bg-inherit"></div>
@ -28,5 +29,5 @@ const giteaLink = `${GIT_URL}/martials/martials.no`
{m.status()}
</ExternalLink>
</div>
<LanguageButtonGroup />
<LanguageButtonGroup client:load />
</div>

View File

@ -1,9 +1,10 @@
---
import LocaleLink from "./links/LocaleLink.astro"
import { type NavLink, resolvePathname } from "@/utils/linking"
import { type NavLink } from "@/utils/linking"
import { deLocalizeHref } from "@/paraglide/runtime"
const pathname = Astro.url.pathname
const currentPath = resolvePathname(pathname)
const currentPath = deLocalizeHref(pathname)
const isEnglish = pathname.startsWith("/en")
---
@ -14,7 +15,7 @@ const isEnglish = pathname.startsWith("/en")
class:list={[
"btn join-item !text-cat-text border-cat-surface0",
!isEnglish ? "bg-cat-mantle" : "bg-cat-base",
]}>Norsk</LocaleLink
]} client:load>Norsk</LocaleLink
>
<LocaleLink
to={currentPath as NavLink}
@ -22,6 +23,6 @@ const isEnglish = pathname.startsWith("/en")
class:list={[
"btn join-item !text-cat-text border-cat-surface0",
isEnglish ? "bg-cat-mantle" : "bg-cat-base",
]}>English</LocaleLink
]} client:load>English</LocaleLink
>
</div>

View File

@ -0,0 +1,29 @@
<script lang="ts">
import { getLocale, type Locale, setLocale } from "@/paraglide/runtime"
const isEnglish = getLocale() === "en"
function updateLocale(lang: Locale) {
setLocale(lang)
}
</script>
<div class="join">
<button
onclick={() => updateLocale("nb")}
class={[
"btn join-item !text-cat-text border-cat-surface0",
!isEnglish ? "bg-cat-mantle" : "bg-cat-base",
]}>Norsk
</button
>
<button
onclick={() => updateLocale("en")}
class={[
"btn join-item !text-cat-text border-cat-surface0",
isEnglish ? "bg-cat-mantle" : "bg-cat-base",
]}>English
</button
>
</div>

View File

@ -53,11 +53,7 @@ LinkedIn: linkedin.com/in/johndoe`,
if (input === "clear") {
history = []
} else {
history = [
...history,
`${currentDir} $ ${input}`,
executeCommand(input),
]
history = [...history, `${currentDir} $ ${input}`, executeCommand(input)]
}
input = ""
}

View File

@ -2,13 +2,13 @@
import PajamasIcon from "@/components/icons/PajamasIcon.astro"
interface Props {
id: string
for: string
}
const { id } = Astro.props
const { for: forId } = Astro.props
---
<label for={id} aria-label="open sidebar" class="btn btn-square btn-ghost">
<label for={forId} aria-label="open sidebar" class="btn btn-square btn-ghost">
<PajamasIcon
name="pajamas:hamburger"
class="w-6 h-6"

View File

@ -2,22 +2,24 @@
import Navbar from "./Navbar.astro"
import NavbarDrawer from "./NavbarDrawer.astro"
import HamburgerMenuButton from "./HamburgerMenuButton.astro"
import { resolvePathname } from "@/utils/linking"
import Breadcrumb from "../Breadcrumb.astro"
import { deLocalizeHref } from "@/paraglide/runtime"
const currentPath = `~${resolvePathname(Astro.originPathname)}`
const currentPath = `~${deLocalizeHref(Astro.originPathname)}`
const drawerToggleId = "header-drawer"
---
<div class="sm:m-auto">
<div class="drawer drawer-end">
<input id="my-drawer-3" type="checkbox" class="drawer-toggle" />
<input id={drawerToggleId} type="checkbox" class="drawer-toggle" />
<div class="drawer-content flex flex-col">
<!-- Navbar -->
<div class="navbar w-full justify-end">
<div class="flex justify-between items-center w-full h-full sm:hidden">
<h1 class="!text-2xl h-5">
{currentPath}
<h1 class="!text-xl h-5">
<Breadcrumb />
</h1>
<HamburgerMenuButton id="my-drawer-3" />
<HamburgerMenuButton for={drawerToggleId} />
</div>
<div class="hidden flex-none sm:block">
<Navbar />
@ -25,8 +27,11 @@ const currentPath = `~${resolvePathname(Astro.originPathname)}`
</div>
</div>
<div class="drawer-side z-50">
<label for="my-drawer-3" aria-label="close sidebar" class="drawer-overlay"
></label>
<label
for={drawerToggleId}
aria-label="close sidebar"
class="drawer-overlay"></label>
<!-- Drawer -->
<ul class="menu bg-cat-base min-h-full w-80 p-4">
<li class="text-xl font-bold my-5">
{currentPath}

View File

@ -1,16 +1,17 @@
---
import { languageTag, type AvailableLanguageTag } from "@/paraglide/runtime"
import { localizePathname, type NavLink } from "@/utils/linking"
import { localizeHref, getLocale, type Locale } from "@/paraglide/runtime"
import { type NavLink } from "@/utils/linking"
import type { ComponentProps } from "@/types/props"
interface Props extends ComponentProps {
to: NavLink
lang?: AvailableLanguageTag
lang?: Locale
}
const { to, class: clazz, lang = languageTag() } = Astro.props
const { to, class: clazz, lang = getLocale() } = Astro.props
---
<a href={localizePathname(to, lang)} class={clazz}>
<!-- TODO currently not working on Paraglide 2 https://github.com/opral/inlang-paraglide-js/issues/472 -->
<a href={localizeHref(to, { locale: lang })} class={clazz}>
<slot />
</a>

View File

@ -3,7 +3,7 @@ import * as m from "@/paraglide/messages"
import Layout from "@/layouts/Layout.astro"
import BadgeList from "@/components/badge/BadgeList.astro"
import GiteaLink from "@/components/links/GiteaLink.astro"
import { languageTag } from "@/paraglide/runtime"
import { getLocale } from "@/paraglide/runtime"
import { getEntry, render } from "astro:content"
import { Image } from "astro:assets"
import dayjs from "dayjs"
@ -16,7 +16,10 @@ interface Props {
const { project } = Astro.props
const entry = await getEntry("projects", project)
const { Content } = await render(entry!)
if (!entry) {
throw new Error("Project not found")
}
const { Content } = await render(entry)
const {
lang,
title,
@ -28,13 +31,14 @@ const {
source,
createdAt,
updatedAt,
} = entry!.data
} = entry.data
function localeDateString(isoString: string): string {
if (languageTag() === "nb") {
return dayjs(isoString).locale(languageTag()).format("DD/MM/YYYY")
let template = "DD-MM-YYYY"
if (getLocale() === "nb") {
template = "DD/MM/YYYY"
}
return dayjs(isoString).locale(languageTag()).format("DD-MM-YYYY")
return dayjs(isoString).locale(getLocale()).format(template)
}
---

View File

@ -2,7 +2,7 @@ import { defineCollection, z } from "astro:content"
import { glob } from "astro/loaders"
const projectCollection = defineCollection({
loader: glob({ pattern: "**\/*.mdx", base: "./src/content/projects" }),
loader: glob({ pattern: "**/*.mdx", base: "./src/content/projects" }),
schema: ({ image }) =>
z.object({
lang: z.union([z.literal("en"), z.literal("nb")]),
@ -19,7 +19,7 @@ const projectCollection = defineCollection({
})
const usesCollection = defineCollection({
loader: glob({ pattern: "**\/*.yaml", base: "./src/content/uses" }),
loader: glob({ pattern: "**/*.yaml", base: "./src/content/uses" }),
schema: z.object({
title: z.string(),
accessories: z.optional(z.array(z.string())),

View File

@ -1,3 +1,3 @@
title: Homelab
hardware:
- b # Graphics cards, CPUs, etc.
- HP ProDesk 600 G3 SFF i7 6. gen # https://bergenbruktpc.no/stasjonaer-pc/hp/hp-prodesk-600-g3-sff-i5-i7-6-gen#&variation=926583

View File

@ -1,5 +1,5 @@
title: Raspberry Pi 4
accessories:
- a # Screens, keyboards, mice, etc.
- 4 TB External harddrive
hardware:
- b # Graphics cards, CPUs, etc.
- OKdo Raspberry Pi 4 Kit 4 GB # https://www.kjell.com/no/produkter/data/raspberry-pi/okdo-raspberry-pi-4-kit-4-gb-p88059

View File

@ -1,8 +1,8 @@
---
import Footer from "@/components/Footer.astro"
import Header from "@/components/header/Header.astro"
import { languageTag } from "@/paraglide/runtime"
import { resolvePathname } from "@/utils/linking"
import Breadcrumb from "@/components/Breadcrumb.astro"
import { getLocale } from "@/paraglide/runtime"
interface Props {
title: string
@ -16,7 +16,7 @@ const mainClass =
---
<!doctype html>
<html lang={languageTag()} dir={"ltr"}>
<html lang={getLocale()} dir={"ltr"}>
<head>
<meta charset="UTF-8" />
<meta name="author" content="Martin Berg Alstad" />
@ -33,7 +33,7 @@ const mainClass =
<Header />
<main class:list={[mainClass, clazz]}>
<h1 class="text-center not-sm:hidden">
~{resolvePathname(Astro.originPathname)}
<Breadcrumb />
</h1>
<div class="my-5">
<slot />

6
src/middleware.ts Normal file
View File

@ -0,0 +1,6 @@
import { paraglideMiddleware } from "@/paraglide/server"
import { defineMiddleware } from "astro/middleware"
export const onRequest = defineMiddleware((context, next) => {
return paraglideMiddleware(context.request, () => next());
});

View File

@ -1,17 +1,9 @@
---
import ProjectPage from "@/components/projects/ProjectPage.astro"
import { type GetStaticPathsResult } from "astro"
import "@/styles/global.css"
// Prerender the page as static HTML during build
export const prerender = true
export function getStaticPaths(): GetStaticPathsResult {
return [
{ params: { project: "homepage" } },
{ params: { project: "sb1budget" } },
]
}
// Prerender must be false for paraglide js
export const prerender = false
const { project } = Astro.params
---

View File

@ -1,17 +1,9 @@
---
import ProjectPage from "@/components/projects/ProjectPage.astro"
import { type GetStaticPathsResult } from "astro"
import "@/styles/global.css"
// Prerender the page as static HTML during build
export const prerender = true
export function getStaticPaths(): GetStaticPathsResult {
return [
{ params: { project: "homepage" } },
{ params: { project: "sb1budget" } },
]
}
// Prerender must be false for paraglide js
export const prerender = false
const { project } = Astro.params
---

View File

@ -1,4 +1,3 @@
import type { AvailableLanguageTag } from "@/paraglide/runtime.js"
import type { AbsolutePathname, Project } from "@/types/types.ts"
interface TranslatedPathnames {
@ -36,30 +35,3 @@ for (const path of paths) {
en: `/en${path}`,
}
}
export function localizePathname(
pathname: NavLink,
locale: AvailableLanguageTag,
): string {
const pathnameParts = pathname.split("/")
const firstSegment: AbsolutePathname = `/${pathnameParts[1]}`
if (pathnames[firstSegment]) {
const localizedPathname = pathnames[firstSegment][locale]
const rest = pathnameParts.slice(2)
if (rest.length > 0) {
return `${localizedPathname}/${rest.join("/")}`
} else {
return localizedPathname
}
}
return pathname
}
export function resolvePathname(pathname: string): AbsolutePathname {
if (pathname.startsWith("/en")) {
return pathname.slice(3) as AbsolutePathname
}
return pathname as AbsolutePathname
}