diff --git a/src/back/config.ts b/src/back/config.ts
index 38515c1..1d3ce90 100644
--- a/src/back/config.ts
+++ b/src/back/config.ts
@@ -1,17 +1,18 @@
 export const SEALIOUS_SANITY = Boolean(process.env.SEALIOUS_SANITY);
 export const PORT = process.env.SEALIOUS_PORT
 	? parseInt(process.env.SEALIOUS_PORT)
 	: 8080;
 export const BASE_URL = process.env.SEALIOUS_BASE_URL || `http://localhost:${PORT}`;
 export const MONGO_PORT = process.env.SEALIOUS_MONGO_PORT
 	? parseInt(process.env.SEALIOUS_MONGO_PORT)
 	: 20747;
 export const MONGO_HOST = process.env.SEALIOUS_MONGO_HOST || "127.0.0.1";
 export const MAILCATCHER_HOST = process.env.SEALIOUS_MAILCATCHER_HOST || "127.0.0.1";
 export const MAILCATCHER_SMTP_PORT = parseInt(
 	process.env.SEALIOUS_MAILCATCHER_SMTP_PORT || "1026"
 );
 export const MAILCATCHER_API_PORT = parseInt(
 	process.env.SEALIOUS_MAILCATCHER_API_PORT || "1082"
 );
 export const MAILER = process.env.SEALIOUS_MAILER;
+export const DEFAULT_HTML_LANG = "pl";
diff --git a/src/back/html.ts b/src/back/html.ts
index 5bfa232..3ca957b 100644
--- a/src/back/html.ts
+++ b/src/back/html.ts
@@ -1,197 +1,202 @@
 import { FlatTemplatable, Templatable, tempstream } from "tempstream";
 import { Readable } from "stream";
 import { BaseContext } from "koa";
 import { default as default_navbar } from "./routes/common/navbar.js";
 import { toKebabCase } from "js-convert-case";
+import { DEFAULT_HTML_LANG } from "./config.js";
 
 export const defaultHead = (
 	ctx: BaseContext,
 	title: string,
 	options: HTMLOptions
 ) => /* HTML */ `<title>${title} ยท ${ctx.$app.manifest.name}</title>
 	<meta name="viewport" content="width=device-width" />
 	<script async src="/dist/bundle.js"></script>
 	<link
 		href="/dist/main.css${options.autoRefreshCSS
 			? `?${Math.random()}${Math.random()}`
 			: ""}"
 		rel="stylesheet"
 		type="text/css"
 	/>
 	<link href="/dist/fonts/fonts.css" rel="stylesheet" type="text/css" />
 	${options.morphing ? `<meta name="turbo-refresh-method" content="morph" />` : ""}
 	${options.preserveScroll
 		? `<meta name="turbo-refresh-scroll" content="preserve">`
 		: ""}`;
 
 export type HTMLOptions = {
 	preserveScroll?: boolean;
 	morphing?: boolean;
 	navbar?: (ctx: BaseContext) => FlatTemplatable;
 	autoRefreshCSS?: boolean;
 	disableCopyEvent?: boolean;
+	language?: string;
 };
 
 export default function html(
 	ctx: BaseContext,
 	title: string,
 	body: Templatable,
 	htmlOptions: HTMLOptions = {},
 	makeHead: (
 		ctx: BaseContext,
 		title: string,
 		options: HTMLOptions
 	) => Templatable = defaultHead
 ): Readable {
 	ctx.set("content-type", "text/html;charset=utf-8");
 	return tempstream/* HTML */ ` <!DOCTYPE html>
-		<html lang="pl" class="title--${toKebabCase(title)}">
+		<html
+			lang="${htmlOptions.language || DEFAULT_HTML_LANG}"
+			class="title--${toKebabCase(title)}"
+		>
 			<head>
 				${makeHead(ctx, title, htmlOptions)}
 			</head>
 			<body>
 				${(htmlOptions.navbar || default_navbar)(ctx)} ${body}
 				${htmlOptions.autoRefreshCSS
 					? /* HTML */ `<script>
 							function make_new_link() {
 								const new_link = document.createElement("link");
 								new_link.rel = "stylesheet";
 								new_link.href = \`/dist/main.css?\${Math.random()}+\${Math.random()}\`;
 								new_link.type = "text/css";
 								return new_link;
 							}
 
 							function getStyles() {
 								return Array.from(
 									document.querySelectorAll("head link")
 								).filter(
 									(e) => new URL(e.href).pathname == "/dist/main.css"
 								);
 							}
 
 							function cleanup_css() {
 								console.log("clearing styles");
 								getStyles()
 									.slice(0, -1)
 									.forEach((style) => {
 										style.parentElement.removeChild(style);
 									});
 							}
 							document.documentElement.addEventListener(
 								"turbo:morph",
 								cleanup_css
 							);
 
 							const sleep = (time) =>
 								new Promise((resolve) => {
 									setTimeout(resolve, time);
 								});
 
 							const APP_DOWN_ERROR_MESSAGE = "App is currently down";
 
 							function get_status() {
 								return fetch("/status.json").then((r) => r.json());
 							}
 
 							async function wait_for_run_id_to_change() {
 								let first_timestamp;
 								try {
 									const { started_at, status } = await get_status();
 									first_timestamp = started_at;
 								} catch (e) {
 									await wait_for_app_to_be_stable();
 									return;
 								}
 
 								if (!first_timestamp) {
 									throw new Error(APP_DOWN_ERROR_MESSAGE);
 								}
 
 								while (true) {
 									const { started_at, status } =
 										await get_status().catch(() => ({
 											started_at: first_timestamp,
 										}));
 									if (started_at !== first_timestamp) {
 										return;
 									}
 									await sleep(100);
 								}
 							}
 
 							async function wait_for_app_to_be_stable(n = 3) {
 								console.log("Waiting for app to be stable....");
 								let counter = 0;
 								while (true) {
 									const { status } = await get_status().catch((e) => ({
 										status: "down",
 									}));
 									if (status == "running") {
 										console.log(counter);
 										counter++;
 									} else {
 										counter = 0;
 									}
 									if (counter == n) {
 										return;
 									}
 									await sleep(100);
 								}
 							}
 
 							async function wait_for_app_restart() {
 								try {
 									await wait_for_run_id_to_change();
 								} catch (e) {
 									if (e.message !== APP_DOWN_ERROR_MESSAGE) {
 										throw e;
 									}
 								}
 								await wait_for_app_to_be_stable();
 							}
 
 							(async function () {
 								const { started_at, status } = await fetch(
 									"/status.json"
 								).then((r) => r.json());
 								last_known_start_timestamp = started_at;
 								const { port, watch } = await fetch(
 									"/dist/notifier.json"
 								).then((r) => r.json());
 								if (!watch) {
 									console.warning(
 										"Not running auto refresh on watch because the build process is not running in watch mode"
 									);
 									return;
 								}
 								const socket = new WebSocket(\`ws://localhost:\${port}\`);
 								socket.onmessage = async (message) => {
 									if (message.data === "css") {
 										const new_link = make_new_link();
 										new_link.onload = cleanup_css;
 										document
 											.querySelector("head")
 											.appendChild(new_link);
 									}
 									if (message.data === "ts") {
 										document.documentElement.classList.add(
 											"restarting"
 										);
 										await wait_for_app_restart();
 										document.documentElement.dispatchEvent(
 											new Event("ts-rebuilt")
 										);
 										document.documentElement.classList.remove(
 											"restarting"
 										);
 									}
 								};
 							})();
 					  </script>`
 					: ""}
 				${htmlOptions.disableCopyEvent
 					? /* HTML */ "<script>document.addEventListener('copy', (e) => e.preventDefault());</script>"
 					: ""}
 			</body>
 		</html>`;
 }