2024-04-04 19:04:14 +00:00
|
|
|
import { defaultI18nGetter, getRawI18n, onI18nReady, setLanguageDetector, setI18nGetter, isCustomLanguageDetector, isCustomI18nGetter, LANG_QUERY, LANG_COOKIE, setCurrentUnitsGetter } from "facilmap-utils";
|
2024-04-04 20:42:25 +00:00
|
|
|
import messagesEn from "./i18n/en.json";
|
|
|
|
import messagesDe from "./i18n/de.json";
|
2024-03-31 13:51:11 +00:00
|
|
|
import type { i18n } from "i18next";
|
|
|
|
import type { Domain } from "domain";
|
2024-04-04 00:38:11 +00:00
|
|
|
import { Router } from "express";
|
2024-03-31 13:51:11 +00:00
|
|
|
import i18nextHttpMiddleware from "i18next-http-middleware";
|
2024-04-04 00:38:11 +00:00
|
|
|
import { type Socket as SocketIO } from "socket.io";
|
2024-04-04 19:04:14 +00:00
|
|
|
import { unitsValidator, type Units } from "facilmap-types";
|
|
|
|
import { parse } from "cookie";
|
2024-03-31 13:51:11 +00:00
|
|
|
|
|
|
|
const namespace = "facilmap-server";
|
|
|
|
|
|
|
|
declare global {
|
2024-04-04 19:04:14 +00:00
|
|
|
namespace NodeJS {
|
|
|
|
interface Process {
|
|
|
|
domain?: Domain;
|
|
|
|
}
|
|
|
|
}
|
2024-03-31 13:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
declare module 'domain' {
|
2024-04-04 19:04:14 +00:00
|
|
|
interface Domain {
|
|
|
|
facilmap?: {
|
|
|
|
i18n?: i18n;
|
|
|
|
units?: Units;
|
|
|
|
}
|
|
|
|
}
|
2024-03-31 13:51:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onI18nReady((i18n) => {
|
|
|
|
i18n.addResourceBundle("en", namespace, messagesEn);
|
|
|
|
i18n.addResourceBundle("de", namespace, messagesDe);
|
|
|
|
});
|
|
|
|
|
2024-04-04 19:04:14 +00:00
|
|
|
export function getRawDomainI18n(): i18n | undefined {
|
|
|
|
return process.domain?.facilmap?.i18n;
|
|
|
|
}
|
|
|
|
|
2024-04-04 00:38:11 +00:00
|
|
|
export function setRawDomainI18n(i18n: i18n): void {
|
|
|
|
if (!process.domain) {
|
|
|
|
throw new Error("Domain is not initialized");
|
|
|
|
}
|
2024-03-31 13:51:11 +00:00
|
|
|
|
2024-04-04 00:38:11 +00:00
|
|
|
if (!process.domain.facilmap) {
|
|
|
|
process.domain.facilmap = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
process.domain.facilmap.i18n = i18n;
|
|
|
|
}
|
2024-03-31 13:51:11 +00:00
|
|
|
|
2024-04-04 19:04:14 +00:00
|
|
|
export function getDomainUnits(): Units | undefined {
|
|
|
|
return process.domain?.facilmap?.units;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function setDomainUnits(units: Units | undefined): void {
|
|
|
|
if (!process.domain) {
|
|
|
|
throw new Error("Domain is not initialized");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!process.domain.facilmap) {
|
|
|
|
process.domain.facilmap = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
process.domain.facilmap.units = units;
|
2024-04-04 00:38:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const i18nMiddleware = Router();
|
|
|
|
i18nMiddleware.use((req, res, next) => {
|
|
|
|
i18nextHttpMiddleware.handle(getRawI18n())(req, res, next);
|
|
|
|
});
|
|
|
|
i18nMiddleware.use((req, res, next) => {
|
|
|
|
if ((req as any).i18n) {
|
|
|
|
setRawDomainI18n(req.i18n);
|
2024-03-31 13:51:11 +00:00
|
|
|
}
|
2024-04-04 00:38:11 +00:00
|
|
|
|
2024-04-04 19:04:14 +00:00
|
|
|
const queryUnits = req.query.units ? unitsValidator.safeParse(req.query.units) : undefined;
|
|
|
|
if (queryUnits?.success) {
|
|
|
|
setDomainUnits(queryUnits.data);
|
|
|
|
} else {
|
|
|
|
const cookieUnits = req.cookies.units ? unitsValidator.safeParse(req.cookies.units) : undefined;
|
|
|
|
if (cookieUnits?.success) {
|
|
|
|
setDomainUnits(cookieUnits.data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-04 00:38:11 +00:00
|
|
|
next();
|
|
|
|
});
|
|
|
|
|
|
|
|
export async function handleSocketConnection(socket: SocketIO): Promise<void> {
|
|
|
|
await new Promise<void>((resolve, reject) => {
|
|
|
|
const req = {
|
|
|
|
query: socket.handshake.query,
|
|
|
|
url: socket.handshake.url,
|
2024-04-04 19:04:14 +00:00
|
|
|
headers: socket.handshake.headers,
|
|
|
|
cookies: socket.handshake.headers.cookie ? parse(socket.handshake.headers.cookie) : Object.create(null)
|
2024-04-04 00:38:11 +00:00
|
|
|
} as any;
|
|
|
|
|
|
|
|
const res = {
|
|
|
|
headers: {},
|
|
|
|
setHeader: () => undefined
|
|
|
|
} as any;
|
|
|
|
|
|
|
|
i18nMiddleware(req, res, (err) => {
|
|
|
|
if (err) {
|
|
|
|
reject(err);
|
|
|
|
} else {
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2024-03-31 13:51:11 +00:00
|
|
|
|
2024-04-03 19:25:51 +00:00
|
|
|
if (!isCustomLanguageDetector) {
|
2024-04-04 00:38:11 +00:00
|
|
|
setLanguageDetector(i18nextHttpMiddleware.LanguageDetector, {
|
|
|
|
order: ["querystring", "cookie", "header"],
|
|
|
|
lookupQuerystring: LANG_QUERY,
|
|
|
|
lookupCookie: LANG_COOKIE
|
|
|
|
});
|
2024-04-03 19:25:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!isCustomI18nGetter) {
|
|
|
|
setI18nGetter(() => {
|
2024-04-04 00:38:11 +00:00
|
|
|
return getRawDomainI18n() ?? defaultI18nGetter();
|
2024-04-03 19:25:51 +00:00
|
|
|
});
|
|
|
|
}
|
2024-03-31 13:51:11 +00:00
|
|
|
|
2024-04-04 19:04:14 +00:00
|
|
|
setCurrentUnitsGetter(() => getDomainUnits());
|
|
|
|
|
2024-04-04 00:38:11 +00:00
|
|
|
export function getI18n(): {
|
|
|
|
t: i18n["t"];
|
|
|
|
changeLanguage: (lang: string) => Promise<void>;
|
|
|
|
} {
|
2024-03-31 13:51:11 +00:00
|
|
|
return {
|
2024-04-04 00:38:11 +00:00
|
|
|
t: getRawI18n().getFixedT(null, namespace),
|
|
|
|
changeLanguage: async (lang) => {
|
|
|
|
const i18n = getRawDomainI18n();
|
|
|
|
if (!i18n) {
|
|
|
|
throw new Error("Domain not initialized, refusing to change language for main instance.");
|
|
|
|
}
|
|
|
|
|
|
|
|
await i18n.changeLanguage(lang);
|
|
|
|
}
|
2024-03-31 13:51:11 +00:00
|
|
|
};
|
|
|
|
}
|