Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Language Detector Middleware for Hono #3785

Open
lord007tn opened this issue Dec 31, 2024 · 2 comments · May be fixed by #3787
Open

Language Detector Middleware for Hono #3785

lord007tn opened this issue Dec 31, 2024 · 2 comments · May be fixed by #3787
Labels
enhancement New feature or request.

Comments

@lord007tn
Copy link

What is the feature you are proposing?

Background

While building an i18n system for Hono, I noticed the lack of a standardized way to detect user language preferences across different sources (URL, cookies, headers, etc.). This is a crucial component for internationalization, and currently, each developer needs to implement their own solution.

Current Situation

Currently in Hono:

  • No built-in way to detect user language preferences
  • No standardized approach for language detection
  • Developers need to write custom code for each project

Proposed Solution

A language detector middleware that:

  • Detects user language from multiple sources (URL path, query params, cookies, Accept-Language header)
  • Provides type-safe access to detected language via c.get('language')
  • Follows i18next's language detection patterns (widely adopted in the JS ecosystem)
  • Is highly configurable yet simple to use
  • Can be used as a foundation for other i18n-related Hono middlewares

Basic usage example:

import { languageDetector } from 'hono/language'

app.use('*', languageDetector({
  supportedLanguages: ['en', 'ar', 'es'],
  fallbackLanguage: 'en'
}))

app.get('/', (c) => {
  const lang = c.get('language') // type-safe access
  return c.text(`Current language: ${lang}`)
})
@lord007tn lord007tn added the enhancement New feature or request. label Dec 31, 2024
@lord007tn lord007tn linked a pull request Dec 31, 2024 that will close this issue
@yusukebe
Copy link
Member

yusukebe commented Dec 31, 2024

Hi @lord007tn

Thank you for the proposal.

It will be helpful. You can do a similar thing with the Accepts Helper:

import { accepts } from 'hono/accepts'
import { Hono } from 'hono'

type Env = {
  Variables: {
    language: string
  }
}

const app = new Hono<Env>()

app.use(async (c, next) => {
  const language = accepts(c, {
    header: 'Accept-Language',
    supports: ['en', 'ja', 'zh'],
    default: 'en'
  })
  c.set('language', language)
  await next()
})

app.get('/', (c) => {
  const lang = c.get('language')
  return c.text(`Current language: ${lang}`)
})

export default app

But, your suggestion and the middleware with your PR have other convenient features, such as language normalizer. Looks good. We have to work on considering whether to add the middleware or not. I will also think about it. Thanks!

@lord007tn
Copy link
Author

accepts only limited to header in my case it is a series of fallbacks that you configure to get the user language

If it is only header, I am okay with you but in the case of path query cookies we need to implement custom logic each time

also if hono is planning to add a feature proof i18n ( its a crucial part of mid-size to large applications, and multinational Saas ) they can depend on that kind of middleware

also the full use of the middleware options is:

app.use(
  '*',
  languageDetector({
    // Detection strategies and their order
    order: ['path', 'querystring', 'cookie', 'header'],

    // Supported languages and fallback
    supportedLanguages: ['en', 'ar'],
    fallbackLanguage: 'en',

    // Query parameter settings
    lookupQuerystring: 'lang', // ?lang=en

    // Path settings
    lookupFromPathIndex: 0, // /en/about -> takes 'en'

    // Cookie settings
    lookupCookie: 'user-language',
    caches: false, // Set to false to disable caching

    // Header settings
    lookupFromHeaderKey: 'accept-language',

    // Language code handling
    ignoreCase: true,
    convertDetectedLanguage: (lang: string) => {
      // Optional: Convert language codes
      // e.g., 'en-US' -> 'en'
      return lang?.split('-')[0]?.toLowerCase() ?? '';
    },

    // Debugging
    debug: process.env.NODE_ENV !== 'production',
  }),
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants