Gitfed
bastien-mrq/gitfed / cmd / gitfed-web / lang.go
package main

import (
	"net/http"
	"strings"
	"time"

	"git.neuromancer.ovh/bastien-mrq/gitfed/internal/i18n"
)

const langCookieName = "gitfed_lang"

// lang resolves the UI language for a request: an explicit cookie (set via
// the nav switcher) wins, then the browser's Accept-Language header, then
// i18n.Default.
func (s *server) lang(r *http.Request) i18n.Lang {
	if c, err := r.Cookie(langCookieName); err == nil {
		if l, ok := i18n.ParseLang(c.Value); ok {
			return l
		}
	}
	for _, part := range strings.Split(r.Header.Get("Accept-Language"), ",") {
		tag := strings.ToLower(strings.TrimSpace(strings.SplitN(part, ";", 2)[0]))
		tag, _, _ = strings.Cut(tag, "-")
		if l, ok := i18n.ParseLang(tag); ok {
			return l
		}
	}
	return i18n.Default
}

// handleSetLang stores the chosen language in a cookie and bounces back to
// wherever the switcher was clicked from.
func (s *server) handleSetLang(w http.ResponseWriter, r *http.Request) {
	if _, ok := i18n.ParseLang(r.PathValue("lang")); ok {
		http.SetCookie(w, &http.Cookie{
			Name:     langCookieName,
			Value:    r.PathValue("lang"),
			Path:     "/",
			HttpOnly: true,
			Secure:   true,
			SameSite: http.SameSiteLaxMode,
			Expires:  time.Now().Add(365 * 24 * time.Hour),
		})
	}
	next := r.URL.Query().Get("next")
	if next == "" || !strings.HasPrefix(next, "/") || strings.HasPrefix(next, "//") {
		next = "/"
	}
	http.Redirect(w, r, next, http.StatusSeeOther)
}