reference
lib
paraglide
getting-started
Standalone Servers

Standalone Servers

This guide covers setting up Paraglide with standalone server frameworks like Hono, Express, Fastify, or Elysia - without a meta-framework like Next.js or SvelteKit.

Paraglide's middleware is simple: request in, response out. It detects the locale and gets out of your way - no routing takeover, no magic.

Setup

npx @inlang/paraglide-js init

This installs dependencies, creates message files, and sets up compilation.

Compiling Messages

Without a bundler plugin, compile messages via CLI:

npx @inlang/paraglide-js compile --project ./project.inlang --outdir ./src/paraglide

Add to your package.json scripts:

{
  "scripts": {
    "build": "paraglide-js compile --project ./project.inlang --outdir ./src/paraglide && your-build-command",
    "dev": "paraglide-js compile --project ./project.inlang --outdir ./src/paraglide && your-dev-command"
  }
}

Or compile programmatically at startup:

import { compile } from "@inlang/paraglide-js";
 
await compile({
  project: "./project.inlang",
  outdir: "./src/paraglide",
});

Framework Examples

Hono

import { Hono } from "hono";
import { paraglideMiddleware } from "./src/paraglide/server.js";
import { getLocale } from "./src/paraglide/runtime.js";
import * as m from "./src/paraglide/messages.js";
 
const app = new Hono();
 
app.use("*", (c, next) => {
  return paraglideMiddleware(c.req.raw, () => next());
});
 
app.get("/", (c) => {
  return c.json({
    locale: getLocale(),
    message: m.hello({ name: "World" }),
  });
});
 
export default app;

Express

Express uses Node.js request/response objects, so you need to convert to Web API Request:

import express from "express";
import { paraglideMiddleware } from "./src/paraglide/server.js";
import { getLocale } from "./src/paraglide/runtime.js";
import * as m from "./src/paraglide/messages.js";
 
const app = express();
 
app.use(async (req, res, next) => {
  const url = `${req.protocol}://${req.get("host")}${req.originalUrl}`;
  const webRequest = new Request(url, {
    method: req.method,
    headers: new Headers(req.headers as Record<string, string>),
  });
 
  await paraglideMiddleware(webRequest, async ({ locale }) => {
    req.locale = locale;
    return new Response();
  });
 
  next();
});
 
app.get("/", (req, res) => {
  res.json({
    locale: getLocale(),
    message: m.hello({ name: "World" }),
  });
});
 
app.listen(3000);

Fastify

import Fastify from "fastify";
import { paraglideMiddleware } from "./src/paraglide/server.js";
import { getLocale } from "./src/paraglide/runtime.js";
import * as m from "./src/paraglide/messages.js";
 
const app = Fastify();
 
app.addHook("preHandler", async (req, reply) => {
  const url = `${req.protocol}://${req.hostname}${req.url}`;
  const webRequest = new Request(url, {
    method: req.method,
    headers: new Headers(req.headers as Record<string, string>),
  });
 
  await paraglideMiddleware(webRequest, async ({ locale }) => {
    req.locale = locale;
    return new Response();
  });
});
 
app.get("/", async (req, reply) => {
  return {
    locale: getLocale(),
    message: m.hello({ name: "World" }),
  };
});
 
app.listen({ port: 3000 });

Elysia

import { Elysia } from "elysia";
import { paraglideMiddleware } from "./src/paraglide/server.js";
import { getLocale } from "./src/paraglide/runtime.js";
import * as m from "./src/paraglide/messages.js";
 
const app = new Elysia()
  .derive(async ({ request }) => {
    let locale = "en";
    await paraglideMiddleware(request, async ({ locale: l }) => {
      locale = l;
      return new Response();
    });
    return { locale };
  })
  .get("/", () => ({
    locale: getLocale(),
    message: m.hello({ name: "World" }),
  }))
  .listen(3000);

Configuration

Configure locale detection strategy in your compile options:

await compile({
  project: "./project.inlang",
  outdir: "./src/paraglide",
  strategy: ["url", "cookie", "preferredLanguage", "baseLocale"],
});

Or via CLI:

npx @inlang/paraglide-js compile \
  --project ./project.inlang \
  --outdir ./src/paraglide \
  --strategy url,cookie,preferredLanguage,baseLocale

See Also