☰
Detecting and Setting the User‘s Locale in Go Web Applications
2026/10/1 8:12:57 网站建设 项目流程
  • 文档
  • 教程

【免费下载链接】build-web-application-with-golang

A golang ebook intro how to build a web with golang

项目地址:https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang
点击查看免费下载

国际化(i18n)与本地化(l10n)是面向全球用户构建 Web 应用的基础能力,而这一切的起点是正确检测并设置用户所属的地区(Locale)。本文以 build-web-application-with-golang 项目的第 10 章(de/10.1.md)为核心,系统讲解 Locale 的组成规则,以及通过域名、URL 参数、客户端信息三种途径在 Go 应用中设置用户地区的完整方案与可运行代码,帮助你为自己的 Web 应用搭建多语言支持的第一块基石。

什么是 Locale

Locale 是一组用于描述某个特定地理区域文本格式与语言习惯的集合,它可能包含语言习惯、文本格式、文化惯用语以及其他大量相关设置。一个 Locale 名称通常由三部分组成:

  1. 语言缩写(必填):标识语言的缩写,例如en表示英文,zh表示中文。
  2. 国家说明符(可选):跟在语言缩写之后,以连字符(-)分隔,用于区分讲同一种语言的不同国家。例如en-US表示美国英语,en-GB表示英国英语。
  3. 字符集说明符(可选):附加在 Locale 名称末尾,以句点(.)分隔,用于指定使用的字符集。例如zh-CN.gb2312表示中国地区使用 gb2312 字符集。

由于 Go 语言默认采用 UTF-8 编码,在 Go 应用中实现 i18n 时通常不需要考虑第三部分(字符集)。因此本书示例统一采用 Locale 名称的前两部分作为标准的 i18n Locale 名,例如en、zh-CN、zh-TW。

提示:在 Linux 和 Solaris 系统中,可以使用locale -a命令列举系统支持的全部地区名,这些命名规范可以当作常见 Locale 的参考样例。对于 BSD 等其他系统,没有locale命令,但地区信息存储在/usr/share/locale目录中。

设置 Locale 的总体思路

明确了 Locale 的定义之后,下一步就是根据访问用户的信息来设置与之匹配的 Locale。可用的用户信息来源包括:

  • 访问信息(访问的域名、URL 参数)
  • 客户端信息(浏览器设置的Accept-Language请求头、用户 IP 地址)
  • 个人信息(用户注册时填写的所在地、在个人资料中保存的语言偏好)

下面分别介绍三种主流设置方式及其代码实现。

通过域名设置 Locale

在应用运行过程中,可以采用域名分级(domain hierarchy)的方式设置 Locale。例如,将www.asta.com作为默认的英文站点,将www.asta.cn作为中文站点,通过建立「域名 ↔ Locale」的对应关系即可完成地区设置。这种方案有几点明显的优势:

  • 通过 URL 就能直观、无歧义地识别用户所属地区;
  • 用户凭借域名即可直觉地知道将要访问哪种语言的站点;
  • 在 Go 程序中实现非常简单方便,通过一个 map 或 if-else 分支即可完成;
  • 有利于搜索引擎爬虫识别,能够提高站点的 SEO 效果。

对应的 Go 代码如下:

if r.Host == "www.asta.com" { i18n.SetLocale("en") } else if r.Host == "www.asta.cn" { i18n.SetLocale("zh-CN") } else if r.Host == "www.asta.tw" { i18n.SetLocale("zh-TW") }

除了使用完整的域名,还可以通过子域名来设置地区,例如en.asta.com表示英文站点、cn.asta.com表示中文站点。实现时只需用strings.Split切分r.Host,取第一段作为语言标识:

prefix := strings.Split(r.Host, ".") if prefix[0] == "en" { i18n.SetLocale("en") } else if prefix[0] == "cn" { i18n.SetLocale("zh-CN") } else if prefix[0] == "tw" { i18n.SetLocale("zh-TW") }

尽管通过域名设置 Locale 具备上述优点,但在实际开发 Web 应用时一般不会采用这种方式,原因在于:

  • 域名成本高:每支持一个 Locale 就需要一个(或一组)域名,且想要申请到名称统一、契合本地语境的域名往往并不容易;
  • 难以统一配置:不愿意为每个站点单独做本地化配置,而是更倾向于在应用层面程序化地处理(例如通过 URL 参数)。

通过 URL 参数设置 Locale

目前最常用的设置 Locale 的方式,是在 URL 中直接携带参数,例如:

  • www.asta.com/hello?locale=zh
  • www.asta.com/zh/hello

对应的设置方式很简单:

i18n.SetLocale(params["locale"])

这种方案几乎拥有通过域名设置 Locale 的所有优点,并且采用 RESTful 风格,无需增加额外的方法来处理。但它的缺点也很明显:需要在每一个链接中增加locale参数,这可能使代码变得复杂甚至相当繁琐。缓解的办法是编写一个通用的 URL 生成函数,让所有链接地址都通过该函数生成,并在函数内部自动追加locale=params["locale"]参数。这样当用户点击链接时,服务端就能轻松从请求中解析出所需 Locale:

locale = params["locale"]

如果想要 URL 更加 RESTful,可以把资源按 Locale 组织在路径中,例如www.asta.com/en/books(英文站点)与www.asta.com/zh/books(中文站点)。这种 URL 形式更有利于 SEO,对用户也更友好——访问者可以直接从 URL 得知目标站点语言。这类 URL 可以通过应用路由(router)来获取 Locale,这与本书 REST 章节(de/08.3.md)介绍的路由插件实现方式一致,示例路由如下:

mux.Get("/:locale/books", listbook)

从源码结构看,本书在 de/03.4.md 中实现的路由器通过mux.match(r.URL.Path)匹配请求路径并分发到对应 handler,因此/:locale/books这类带参数的路由可以自然地把路径中的语言段提取出来,再交给i18n.SetLocale使用。

从客户端信息设置 Locale

在某些特殊场景下,我们需要根据客户端信息而不是 URL 来设置 Locale。这些信息可能来自浏览器设置、用户 IP 地址或用户注册时填写的所在地。这种方式更适合以 Web 为基础的应用。

基于 Accept-Language 请求头

客户端发起请求时,HTTP 头中通常带有Accept-Language字段,标示用户偏好的语言。下面是 Go 实现的一个简单的解析示例:

AL := r.Header.Get("Accept-Language") if AL == "en" { i18n.SetLocale("en") } else if AL == "zh-CN" { i18n.SetLocale("zh-CN") } else if AL == "zh-TW" { i18n.SetLocale("zh-TW") }

当然,在实际应用中往往需要更严格的判断规则来设置地区。例如Accept-Language的真实取值可能是zh-CN,zh;q=0.9,en;q=0.8这样的带权重列表,而不是单一值,这时需要先按逗号切分、解析质量因子(q 值)再决定最终 Locale,而不是简单地做全等比较。

基于 IP 地址

另一种根据客户端设定地区的方式是利用用户访问的 IP 地址。借助 IP 地址库(如目前全球较为常用的 GeoIP GeoLite Country / City 库),可以将访问 IP 映射到对应的国家或地区。实现机制非常简单:根据 IP 数据库查询用户的 IP,返回对应的国家地区信息,再根据返回结果设置相应的 Locale。

基于用户 Profile(个人资料)

还可以让用户通过下拉菜单等输入组件主动选择自己的 Locale,并将该信息保存到与账号关联的 profile 中。当用户再次登录时,把这份设置写回 Locale 配置,从而保证该用户每次访问站点时都能基于自己先前设定的语言获得页面内容。

如何选择设置方式

通过上文介绍可知,设置 Locale 可以有多种方式,实际项目中应根据需求灵活组合:

设置方式优点缺点 / 适用前提
完整域名(www.asta.com / www.asta.cn)识别清晰、用户直觉友好、实现简单、利于 SEO每个 Locale 都需要独立域名,成本高
子域名(en.asta.com / cn.asta.com)实现简单,域名开销相对可控需要为每个 Locale 规划子域名
URL 参数(?locale=zh)RESTful、无需额外方法、覆盖大多数场景每个链接都要携带 locale 参数,需统一 URL 生成函数
路径式 URL(/en/books)更 RESTful、利于 SEO、用户友好依赖路由对:locale参数的支持
Accept-Language 请求头零用户操作、自动匹配浏览器语言真实头信息通常带权重列表,需要更严格的解析
IP 地址无需用户干预、可覆盖匿名访问依赖 IP 地址库的准确性与更新
用户 Profile用户可主动定制、体验一致需要登录体系与资料存储支持

在具体实现中,多语言站点往往采用「URL 优先、请求头兜底」的混合策略:先尝试从 URL 或路径参数提取 Locale,未命中时再回退到Accept-Language、IP 或用户 profile。

总结

本文演示了多种检测并设置用户 Locale 的方法:通过完整域名、子域名、URL 参数,以及直接基于客户端信息(Accept-Language、IP 地址、用户 profile)等方式。为特定地区的用户提供贴近其语言习惯与本地语境的页面,是构建国际化 Web 应用的第一步。设置好 Locale 之后,下一步就是解决「如何按 Locale 存储与取出对应的资源」问题——这部分内容请继续阅读本书的 本地化资源(10.2) 一节,其中讲解了文本、日期时间、货币以及视图资源的本地化方案;而完整的多语言包加载与模板函数集成则在 国际化站点(10.3) 一节中展开。

相关章节链接

  • 目录
  • 上一节:国际化和本地化(10.0)
  • 下一节:本地化资源(10.2)
  • 延伸阅读:REST 实现(8.3)、构建 Web 应用的基础路由(3.4)
  • 文档
  • 教程

【免费下载链接】build-web-application-with-golang

A golang ebook intro how to build a web with golang

项目地址:https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang
点击查看免费下载
上一篇:GTA5线上小助手传送功能实操指南:从第一次瞬移到一个月后的传送达人,告别洛圣都无效跑图
下一篇:GTA5线上小助手传送怎么用?3大高效实战玩法与避坑指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询