You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Astro组件全局共享状态:如何实现客户端语言偏好设置

Astro JS 多语言切换实现方案

核心思路

结合客户端存储(localStorage)和 Astro 的中间件、全局布局,实现客户端偏好设置+服务端渲染时读取偏好,确保所有组件能获取到当前语言。

步骤1:全局布局中实现切换逻辑

在全局布局组件(如Layout.astro)中添加切换按钮,同时处理客户端存储和页面更新逻辑:

---
// Layout.astro
import { Astro } from 'astro';

// 服务端读取:优先取cookie值,默认pt-br
const lang = Astro.cookies.get('lang')?.value || 'pt-br';
---
<!DOCTYPE html>
<html lang={lang}>
<head>
  <meta charset="UTF-8">
  <title>{Astro.props.title}</title>
  <style>
    #langBtn .active { color: #2563eb; font-weight: bold; }
  </style>
</head>
<body>
  <!-- 语言切换按钮 -->
  <div id="langBtn">
    <span data-lang="pt-br" class={lang === 'pt-br' ? 'active' : ''}>BR</span>
    <span>|</span>
    <span data-lang="en" class={lang === 'en' ? 'active' : ''}>EN</span>
  </div>

  <slot />

  <script>
    // 客户端初始化:读取localStorage,若与当前页面语言不一致则触发刷新
    const savedLang = localStorage.getItem('lang');
    if (savedLang && savedLang !== document.documentElement.lang) {
      window.location.href = `${window.location.pathname}?lang=${savedLang}`;
    }

    // 按钮点击事件:存储偏好并触发服务端重新渲染
    document.getElementById('langBtn').addEventListener('click', (e) => {
      const targetLang = e.target.dataset.lang;
      if (!targetLang) return;
      
      localStorage.setItem('lang', targetLang);
      window.location.href = `${window.location.pathname}?lang=${targetLang}`;
    });
  </script>
</body>
</html>

步骤2:中间件同步语言到Cookie

创建src/middleware.ts,读取URL参数中的语言值并存入Cookie,确保服务端渲染时能直接读取:

// src/middleware.ts
import { defineMiddleware } from 'astro:middleware';

export const onRequest = defineMiddleware(async (context, next) => {
  const langParam = context.url.searchParams.get('lang');
  // 仅允许预设的语言值
  if (langParam && ['pt-br', 'en'].includes(langParam)) {
    context.cookies.set('lang', langParam, {
      path: '/',
      maxAge: 60 * 60 * 24 * 30, // 有效期30天
      httpOnly: false,
    });
    // 重定向去掉URL参数,保持地址栏干净
    return context.redirect(new URL(context.url.pathname, context.url.origin));
  }
  return next();
});

步骤3:组件中使用语言参数

所有子组件可直接通过布局传递的lang属性获取当前语言,比如Hero.astro:

---
// Hero.astro
const { lang } = Astro.props;
---
<section>
  <h1>{lang === 'pt-br' ? 'Olá, eu sou o Daniel!' : 'Hi, I\'m Daniel!'}</h1>
  <p>{lang === 'pt-br' ? 'Bem-vindo ao meu portfólio' : 'Welcome to my portfolio'}</p>
</section>

方案优势

  • 客户端用localStorage记住用户偏好,点击按钮后通过URL参数触发服务端重新渲染,保证组件获取最新语言值
  • 中间件将语言存入Cookie,页面刷新或跳转后,服务端能直接读取并渲染对应语言内容
  • 全局布局统一管理语言状态,无需手动向每个组件传递参数

内容的提问来源于stack exchange,提问作者Daniel Guedes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:40:23