{"id":14969219,"url":"https://github.com/i18next/i18next-http-middleware","last_synced_at":"2025-05-15T03:05:35.248Z","repository":{"id":38453947,"uuid":"257010397","full_name":"i18next/i18next-http-middleware","owner":"i18next","description":"i18next-http-middleware is a middleware to be used with Node.js web frameworks like express or Fastify and also for Deno.","archived":false,"fork":false,"pushed_at":"2025-04-18T20:51:21.000Z","size":183,"stargazers_count":160,"open_issues_count":2,"forks_count":28,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-21T03:50:36.300Z","etag":null,"topics":["deno","express","fastify","i18n","i18next","javascript","middleware","nodejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/i18next.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["jamuhl","adrai"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://locize.com"}},"created_at":"2020-04-19T13:46:34.000Z","updated_at":"2025-04-20T07:49:04.000Z","dependencies_parsed_at":"2025-02-28T18:07:53.498Z","dependency_job_id":"82ccba00-802e-4d4f-b589-c6c5df11d07b","html_url":"https://github.com/i18next/i18next-http-middleware","commit_stats":{"total_commits":182,"total_committers":17,"mean_commits":"10.705882352941176","dds":"0.15384615384615385","last_synced_commit":"af6a6ee1b68384e4c671c9d654899e82e642b6ca"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18next%2Fi18next-http-middleware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18next%2Fi18next-http-middleware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18next%2Fi18next-http-middleware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i18next%2Fi18next-http-middleware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/i18next","download_url":"https://codeload.github.com/i18next/i18next-http-middleware/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254264765,"owners_count":22041793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","express","fastify","i18n","i18next","javascript","middleware","nodejs"],"created_at":"2024-09-24T13:41:23.036Z","updated_at":"2025-05-15T03:05:35.231Z","avatar_url":"https://github.com/i18next.png","language":"JavaScript","readme":"# Introduction\n\n[![Actions](https://github.com/i18next/i18next-http-middleware/workflows/node/badge.svg)](https://github.com/i18next/i18next-http-middleware/actions?query=workflow%3Anode)\n[![Actions deno](https://github.com/i18next/i18next-http-middleware/workflows/deno/badge.svg)](https://github.com/i18next/i18next-http-middleware/actions?query=workflow%3Adeno)\n[![Travis](https://img.shields.io/travis/i18next/i18next-http-middleware/master.svg?style=flat-square)](https://travis-ci.org/i18next/i18next-http-middleware)\n[![npm version](https://img.shields.io/npm/v/i18next-http-middleware.svg?style=flat-square)](https://www.npmjs.com/package/i18next-http-middleware)\n\nThis is a middleware to be used with Node.js web frameworks like express or Fastify and also for Deno.\n\nIt's based on the deprecated [i18next-express-middleware](https://github.com/i18next/i18next-express-middleware) and can be used as a drop-in replacement.\n_It's not bound to a specific http framework anymore._\n\n## Advice:\n\nTo get started with server side internationalization, you may also have a look at [this blog post](https://dev.to/adrai/how-does-server-side-internationalization-i18n-look-like-5f4c) also using [using i18next-http-middleware](https://dev.to/adrai/how-does-server-side-internationalization-i18n-look-like-5f4c#ssr).\n\n# Getting started\n\n```bash\n# npm package\n$ npm install i18next-http-middleware\n```\n\n## wire up i18next to request object\n\n```js\nvar i18next = require('i18next')\nvar middleware = require('i18next-http-middleware')\nvar express = require('express')\n\ni18next.use(middleware.LanguageDetector).init({\n  preload: ['en', 'de', 'it'],\n  ...otherOptions\n})\n\nvar app = express()\napp.use(\n  middleware.handle(i18next, {\n    ignoreRoutes: ['/foo'], // or function(req, res, options, i18next) { /* return true to ignore */ }\n    removeLngFromUrl: false // removes the language from the url when language detected in path\n  })\n)\n\n// in your request handler\napp.get('myRoute', (req, res) =\u003e {\n  var resolvedLng = req.resolvedLanguage // 'de-CH'\n  var lng = req.language // 'de-CH'\n  var lngs = req.languages // ['de-CH', 'de', 'en']\n  req.i18n.changeLanguage('en') // will not load that!!! assert it was preloaded\n\n  var exists = req.i18n.exists('myKey')\n  var translation = req.t('myKey')\n})\n\n// in your views, eg. in pug (ex. jade)\ndiv = t('myKey')\n```\n\n### Fastify usage\n\n```js\nvar i18next = require('i18next')\nvar middleware = require('i18next-http-middleware')\nvar fastify = require('fastify')\n\ni18next.use(middleware.LanguageDetector).init({\n  preload: ['en', 'de', 'it'],\n  ...otherOptions\n})\n\nvar app = fastify()\napp.register(i18nextMiddleware.plugin, {\n  i18next,\n  ignoreRoutes: ['/foo'] // or function(req, res, options, i18next) { /* return true to ignore */ }\n})\n// or\n// app.addHook('preHandler', i18nextMiddleware.handle(i18next, {\n//   ignoreRoutes: ['/foo'] // or function(req, res, options, i18next) { /* return true to ignore */ }\n// }))\n\n// in your request handler\napp.get('myRoute', (request, reply) =\u003e {\n  var lng = request.language // 'de-CH'\n  var lngs = v.languages // ['de-CH', 'de', 'en']\n  request.i18n.changeLanguage('en') // will not load that!!! assert it was preloaded\n\n  var exists = request.i18n.exists('myKey')\n  var translation = request.t('myKey')\n})\n```\n\n### Hapi usage\n\n```js\nconst i18next = require('i18next')\nconst middleware = require('i18next-http-middleware')\nconst Hapi = require('@hapi/hapi')\n\ni18next.use(middleware.LanguageDetector).init({\n  preload: ['en', 'de', 'it'],\n  ...otherOptions\n})\n\nconst server = Hapi.server({\n  port: port,\n  host: '0.0.0.0',\n\nawait server.register({\n  plugin: i18nextMiddleware.hapiPlugin,\n  options: {\n    i18next,\n    ignoreRoutes: ['/foo'] // or function(req, res, options, i18next) { /* return true to ignore\n  }\n})\n\n// in your request handler\nserver.route({\n  method: 'GET',\n  path: '/myRoute',\n  handler: (request, h) =\u003e {\n    var resolvedLng = request.resolvedLanguage // 'de-CH'\n    var lng = request.language // 'de-CH'\n    var lngs = v.languages // ['de-CH', 'de', 'en']\n    request.i18n.changeLanguage('en') // will not load that!!! assert it was preloaded\n\n    var exists = request.i18n.exists('myKey')\n    var translation = request.t('myKey')\n  }\n})\n\n```\n\n### Koa usage\n\n```js\nvar i18next = require('i18next')\nvar middleware = require('i18next-http-middleware')\nconst Koa = require('koa')\nconst router = require('@koa/router')()\n\ni18next.use(middleware.LanguageDetector).init({\n  preload: ['en', 'de', 'it'],\n  ...otherOptions\n})\n\nvar app = new Koa()\napp.use(i18nextMiddleware.koaPlugin(i18next, {\n  ignoreRoutes: ['/foo'] // or function(req, res, options, i18next) { /* return true to ignore */ }\n}))\n\n// in your request handler\nrouter.get('/myRoute', ctx =\u003e {\n  ctx.body = JSON.stringify({\n    'ctx.resolvedLanguage': ctx.resolvedLanguage,\n    'ctx.language': ctx.language,\n    'ctx.i18n.resolvedLanguage': ctx.i18n.resolvedLanguage,\n    'ctx.i18n.language': ctx.i18n.language,\n    'ctx.i18n.languages': ctx.i18n.languages,\n    'ctx.i18n.languages[0]': ctx.i18n.languages[0],\n    'ctx.t(\"home.title\")': ctx.t('home.title')\n  }, null, 2)\n})\n```\n\n### Deno usage\n\n#### abc\n\n```js\nimport i18next from 'https://deno.land/x/i18next/index.js'\nimport Backend from 'https://cdn.jsdelivr.net/gh/i18next/i18next-fs-backend/index.js'\nimport i18nextMiddleware from 'https://deno.land/x/i18next_http_middleware/index.js'\nimport { Application } from 'https://deno.land/x/abc/mod.ts'\nimport { config } from 'https://deno.land/x/dotenv/dotenv.ts'\n\ni18next\n  .use(Backend)\n  .use(i18nextMiddleware.LanguageDetector)\n  .init({\n    // debug: true,\n    backend: {\n      // eslint-disable-next-line no-path-concat\n      loadPath: 'locales/{{lng}}/{{ns}}.json',\n      // eslint-disable-next-line no-path-concat\n      addPath: 'locales/{{lng}}/{{ns}}.missing.json'\n    },\n    fallbackLng: 'en',\n    preload: ['en', 'de']\n  })\n\nconst port = config.PORT || 8080\nconst app = new Application()\nconst handle = i18nextMiddleware.handle(i18next)\napp.use((next) =\u003e (c) =\u003e {\n  handle(c.request, c.response, () =\u003e {})\n  return next(c)\n})\napp.get('/', (c) =\u003e c.request.t('home.title'))\nawait app.start({ port })\n```\n\n#### ServestJS\n\n```js\nimport i18next from 'https://deno.land/x/i18next/index.js'\nimport Backend from 'https://cdn.jsdelivr.net/gh/i18next/i18next-fs-backend/index.js'\nimport i18nextMiddleware from 'https://deno.land/x/i18next_http_middleware/index.js'\nimport { createApp } from 'https://servestjs.org/@v1.0.0-rc2/mod.ts'\nimport { config } from 'https://deno.land/x/dotenv/dotenv.ts'\n\ni18next\n  .use(Backend)\n  .use(i18nextMiddleware.LanguageDetector)\n  .init({\n    // debug: true,\n    backend: {\n      // eslint-disable-next-line no-path-concat\n      loadPath: 'locales/{{lng}}/{{ns}}.json',\n      // eslint-disable-next-line no-path-concat\n      addPath: 'locales/{{lng}}/{{ns}}.missing.json'\n    },\n    fallbackLng: 'en',\n    preload: ['en', 'de']\n  })\n\nconst port = config.PORT || 8080\nconst app = createApp()\napp.use(i18nextMiddleware.handle(i18next))\napp.get('/', async (req) =\u003e {\n  await req.respond({\n    status: 200,\n    headers: new Headers({\n      'content-type': 'text/plain'\n    }),\n    body: req.t('home.title')\n  })\n})\nawait app.listen({ port })\n```\n\n## add routes\n\n```js\n// missing keys make sure the body is parsed (i.e. with [body-parser](https://github.com/expressjs/body-parser#bodyparserjsonoptions))\napp.post('/locales/add/:lng/:ns', middleware.missingKeyHandler(i18next))\n// addPath for client: http://localhost:8080/locales/add/{{lng}}/{{ns}}\n\n// multiload backend route\napp.get('/locales/resources.json', middleware.getResourcesHandler(i18next))\n// can be used like:\n// GET /locales/resources.json\n// GET /locales/resources.json?lng=en\n// GET /locales/resources.json?lng=en\u0026ns=translation\n\n// serve translations:\napp.use('/locales', express.static('locales'))\n// GET /locales/en/translation.json\n// loadPath for client: http://localhost:8080/locales/{{lng}}/{{ns}}.json\n\n// or instead of static\napp.get('/locales/:lng/:ns', middleware.getResourcesHandler(i18next))\n// GET /locales/en/translation\n// loadPath for client: http://localhost:8080/locales/{{lng}}/{{ns}}\n\napp.get('/locales/:lng/:ns', middleware.getResourcesHandler(i18next, {\n  maxAge: 60 * 60 * 24 * 30, // adds appropriate cache header if cache option is passed or NODE_ENV === 'production', defaults to 30 days\n  cache: true // defaults to false\n}))\n```\n\n## add localized routes\n\nYou can add your routes directly to the express app\n\n```js\nvar express = require('express'),\n  app = express(),\n  i18next = require('i18next'),\n  FilesystemBackend = require('i18next-fs-backend'),\n  i18nextMiddleware = require('i18next-http-middleware'),\n  port = 3000\n\ni18next\n  .use(i18nextMiddleware.LanguageDetector)\n  .use(FilesystemBackend)\n  .init({ preload: ['en', 'de', 'it'], ...otherOptions }, () =\u003e {\n    i18nextMiddleware.addRoute(\n      i18next,\n      '/:lng/key-to-translate',\n      ['en', 'de', 'it'],\n      app,\n      'get',\n      (req, res) =\u003e {\n        //endpoint function\n      }\n    )\n  })\napp.use(i18nextMiddleware.handle(i18next))\napp.listen(port, () =\u003e {\n  console.log('Server listening on port', port)\n})\n```\n\nor to an express router\n\n```js\nvar express = require('express'),\n  app = express(),\n  i18next = require('i18next'),\n  FilesystemBackend = require('i18next-fs-backend'),\n  i18nextMiddleware = require('i18next-http-middleware'),\n  router = require('express').Router(),\n  port = 3000\n\ni18next\n  .use(i18nextMiddleware.LanguageDetector)\n  .use(FilesystemBackend)\n  .init({ preload: ['en', 'de', 'it'], ...otherOptions }, () =\u003e {\n    i18nextMiddleware.addRoute(\n      i18next,\n      '/:lng/key-to-translate',\n      ['en', 'de', 'it'],\n      router,\n      'get',\n      (req, res) =\u003e {\n        //endpoint function\n      }\n    )\n    app.use('/', router)\n  })\napp.use(i18nextMiddleware.handle(i18next))\napp.listen(port, () =\u003e {\n  console.log('Server listening on port', port)\n})\n```\n\n## custom http server\n\nDefine your own functions to handle your custom request or response\n\n```js\nmiddleware.handle(i18next, {\n  getPath: (req) =\u003e req.path,\n  getUrl: (req) =\u003e req.url,\n  setUrl: (req, url) =\u003e (req.url = url),\n  getQuery: (req) =\u003e req.query,\n  getParams: (req) =\u003e req.params,\n  getBody: (req) =\u003e req.body,\n  setHeader: (res, name, value) =\u003e res.setHeader(name, value),\n  setContentType: (res, type) =\u003e res.contentType(type),\n  setStatus: (res, code) =\u003e res.status(code),\n  send: (res, body) =\u003e res.send(body)\n})\n```\n\n## language detection\n\nDetects user language from current request. Comes with support for:\n\n- path\n- cookie\n- header\n- querystring\n- session\n\nBased on the i18next language detection handling: https://www.i18next.com/misc/creating-own-plugins#languagedetector\n\nWiring up:\n\n```js\nvar i18next = require('i18next')\nvar middleware = require('i18next-http-middleware')\n\ni18next.use(middleware.LanguageDetector).init(i18nextOptions)\n```\n\nAs with all modules you can either pass the constructor function (class) to the i18next.use or a concrete instance.\n\n## Detector Options\n\n```js\n{\n  // order and from where user language should be detected\n  order: [/*'path', 'session', */ 'querystring', 'cookie', 'header'],\n\n  // keys or params to lookup language from\n  lookupQuerystring: 'lng',\n  lookupCookie: 'i18next',\n  lookupHeader: 'accept-language',\n  lookupHeaderRegex: /(([a-z]{2})-?([A-Z]{2})?)\\s*;?\\s*(q=([0-9.]+))?/gi,\n  lookupSession: 'lng',\n  lookupPath: 'lng',\n  lookupFromPathIndex: 0,\n\n  // cache user language, you can define if an how the detected language should be \"saved\" =\u003e 'cookie' and/or 'session'\n  caches: false, // ['cookie']\n\n  ignoreCase: true, // ignore case of detected language\n\n  // optional expire and domain for set cookie\n  cookieExpirationDate: new Date(),\n  cookieDomain: 'myDomain',\n  cookiePath: '/my/path',\n  cookieSecure: true, // if need secure cookie\n  cookieSameSite: 'strict', // 'strict', 'lax' or 'none'\n\n  // optional conversion function used to modify the detected language code\n  convertDetectedLanguage: 'Iso15897',\n  convertDetectedLanguage: (lng) =\u003e lng.replace('-', '_')\n}\n```\n\nOptions can be passed in:\n\n**preferred** - by setting options.detection in i18next.init:\n\n```js\nvar i18next = require('i18next')\nvar middleware = require('i18next-http-middleware')\n\ni18next.use(middleware.LanguageDetector).init({\n  detection: options\n})\n```\n\non construction:\n\n```js\nvar middleware = require('i18next-http-middleware')\nvar lngDetector = new middleware.LanguageDetector(null, options)\n```\n\nvia calling init:\n\n```js\nvar middleware = require('i18next-http-middleware')\n\nvar lngDetector = new middleware.LanguageDetector()\nlngDetector.init(options)\n```\n\n## Adding own detection functionality\n\n### interface\n\n```js\nmodule.exports = {\n  name: 'myDetectorsName',\n\n  lookup: function (req, res, options) {\n    // options -\u003e are passed in options\n    return 'en'\n  },\n\n  cacheUserLanguage: function (req, res, lng, options) {\n    // options -\u003e are passed in options\n    // lng -\u003e current language, will be called after init and on changeLanguage\n    // store it\n  }\n}\n```\n\n### adding it\n\n```js\nvar i18next = require('i18next')\nvar middleware = require('i18next-http-middleware')\n\nvar lngDetector = new middleware.LanguageDetector()\nlngDetector.addDetector(myDetector)\n\ni18next.use(lngDetector).init({\n  detection: options\n})\n```\n\nDon't forget: You have to add the name of your detector (`myDetectorsName` in this case) to the `order` array in your `options` object. Without that, your detector won't be used. See the [Detector Options section for more](#detector-options).\n\n---\n\n\u003ch3 align='center'\u003eGold Sponsors\u003c/h3\u003e\n\n\u003cp align='center'\u003e\n  \u003ca href='https://locize.com/' target='_blank'\u003e\n    \u003cimg src='https://raw.githubusercontent.com/i18next/i18next/master/assets/locize_sponsor_240.gif' width='240px'\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n","funding_links":["https://github.com/sponsors/jamuhl","https://github.com/sponsors/adrai","https://locize.com"],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi18next%2Fi18next-http-middleware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fi18next%2Fi18next-http-middleware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi18next%2Fi18next-http-middleware/lists"}