fix(lang): redirect par langue reste sur l'hôte courant (.onion compris) + détection langue fiable
- base mailto hote courant via Host header (http pour .onion, https sinon) : canonical/hreflang restent sur le domaine actuel, plus de fuite vers le Funnel - meta refresh rendu relatif et différé à 1.5s pour laisser le JS choisir la langue - localStorage isolé dans son propre try/catch : la détection navigator s'exécute même quand le stockage est bloqué (Tor), plus de Français systématique
This commit is contained in:
parent
d1c994bc7f
commit
03c0c134fe
1 changed files with 23 additions and 14 deletions
|
|
@ -139,9 +139,18 @@ function html(body: string, cache = "no-cache") {
|
|||
})
|
||||
}
|
||||
|
||||
function langRedirectPage(rest: string): string {
|
||||
const fr = `${SITE_URL}/fr${rest}`
|
||||
const en = `${SITE_URL}/en${rest}`
|
||||
function baseUrl(req: Request, fallback = SITE_URL): string {
|
||||
const host = (req.headers.get("host") || "").trim()
|
||||
if (!host) return fallback
|
||||
// Tor = HTTP, tout le reste est servi en HTTPS (le schéma suit l'hôte courant,
|
||||
// pour que la redirection de langue reste sur le domaine actuel, .onion compris).
|
||||
const scheme = host.toLowerCase().endsWith(".onion") ? "http" : "https"
|
||||
return `${scheme}://${host}`
|
||||
}
|
||||
|
||||
function langRedirectPage(rest: string, base: string): string {
|
||||
const fr = `${base}/fr${rest}`
|
||||
const en = `${base}/en${rest}`
|
||||
const restJs = JSON.stringify(rest)
|
||||
return `<!doctype html>
|
||||
<html lang="fr">
|
||||
|
|
@ -154,18 +163,18 @@ function langRedirectPage(rest: string): string {
|
|||
<link rel="alternate" hreflang="fr" href="${fr}" />
|
||||
<link rel="alternate" hreflang="en" href="${en}" />
|
||||
<link rel="alternate" hreflang="x-default" href="${fr}" />
|
||||
<meta http-equiv="refresh" content="0; url=${fr}" />
|
||||
<meta http-equiv="refresh" content="1.5; url=/fr${rest}" />
|
||||
<script>(function(){
|
||||
var rest=${restJs};
|
||||
var saved=null;
|
||||
try{ saved=localStorage.getItem("zektyc-lang"); }catch(e){}
|
||||
var target="/fr"+rest;
|
||||
try{
|
||||
var saved=localStorage.getItem("zektyc-lang");
|
||||
if(saved==="en"||saved==="fr"){ target="/"+saved+rest; }
|
||||
else {
|
||||
var ln=(navigator.language||navigator.userLanguage||"").toLowerCase();
|
||||
if(ln.indexOf("en")===0) target="/en"+rest;
|
||||
}
|
||||
}catch(e){}
|
||||
if(saved==="en"||saved==="fr"){
|
||||
target="/"+saved+rest;
|
||||
} else {
|
||||
var ln=(navigator.languages&&navigator.languages.length?navigator.languages[0]:(navigator.language||navigator.userLanguage||"")).toLowerCase();
|
||||
if(ln.indexOf("en")===0) target="/en"+rest;
|
||||
}
|
||||
if(target.indexOf("/en")===0){
|
||||
fetch(target,{method:"HEAD",cache:"no-store"}).then(function(r){
|
||||
location.replace(r.ok?target:"/fr"+rest);
|
||||
|
|
@ -1288,8 +1297,8 @@ server = serve({
|
|||
return new Response(null, { status: 301, headers: { Location: `/en/zmap${sub}/` } })
|
||||
}
|
||||
const artMatch = matchArticle(pathname, articles)
|
||||
if (artMatch) return html(langRedirectPage(artPath(artMatch)), "no-cache")
|
||||
if (isHtmlFile(pathname)) return html(langRedirectPage(pathname === "/" ? "/" : pathname), "no-cache")
|
||||
if (artMatch) return html(langRedirectPage(artPath(artMatch), baseUrl(req)), "no-cache")
|
||||
if (isHtmlFile(pathname)) return html(langRedirectPage(pathname === "/" ? "/" : pathname, baseUrl(req)), "no-cache")
|
||||
}
|
||||
|
||||
const p = resolveLangPath(pathname) ?? pathname
|
||||
|
|
|
|||
Loading…
Reference in a new issue