- 前端
- 国际化
【免费下载链接】vue-i18n
:globe_with_meridians: Internationalization plugin for Vue.js
本指南以 vue-i18n 仓库中的 Contentful 集成示例(examples/integration/contentful)为主线,完整讲解如何从零注册 Contentful 账号、创建内容空间、生成访问令牌、导入内容模型、编写本地配置文件,直至运行和部署一个由 vue-i18n 驱动双语界面的静态博客站点。读完本指南,你将掌握 Contentful 的 CMA/CDA 双令牌体系、
contentful-import数据导入流程,以及 vue-i18n 如何通过 locale 联动 Contentful 内容检索,实现"界面语言 + 内容语言"一体化切换的完整实战方案。
一、这个示例项目是什么
examples/integration/contentful是 vue-i18n 仓库中的官方集成示例,它演示了一个"5 分钟搭建基于 Contentful 的静态博客"(内容即服务 CMS + Vue 生态)的组合方案:
- Contentful:负责内容的创建、管理与分发,提供 Content Delivery API(CDA)与 Content Management API(CMA);
- Nuxt.js:负责页面渲染、静态生成与路由预取;
- vue-i18n:负责界面文案的国际化,并基于当前 locale 向 Contentful 发起对应语言的查询。
该示例的配套文档 GETTING-STARTED.md 给出了完整的自助搭建步骤,本文将以它为骨架,结合仓库内的 nuxt.config.js、package.json 与 plugins/i18n.js 等源码逐层展开。示例首页、博客详情页与标签页分别位于 pages/index.vue、pages/blog/_slug.vue 和 pages/tags/_tag.vue,语言相关组件在 components/language-header.vue 与 components/navigation.vue。
二、前置条件:注册 Contentful
开始动手之前,需要先在 Contentful 官网完成注册,获得一个可用的账号。整个搭建流程涉及两类内容对象:
| 对象 | 用途 |
|---|---|
| Space(内容空间) | 内容模型与数据的容器,每个项目对应一个独立空间 |
| Access Token(访问令牌) | 分为 CMA 令牌(管理/写入数据)与 CDA 令牌(读取/分发数据)两类 |
后续所有操作都围绕"创建一个空间 + 拿到两类令牌 + 导入数据 + 本地配置"展开。
三、克隆仓库与安装依赖
示例文档给出的标准起步命令如下:
$ git clone <当前仓库地址> && cd vue-i18n $ cd examples/integration/contentful $ npm install在当前仓库中,该示例自带完整的 package.json,核心运行时依赖包括:
contentful:CDA 客户端,用于读取空间数据;contentful-management:CMA 客户端,用于管理端操作(如读取内容类型以枚举标签);nuxt:示例基于 Nuxt 1.x 构建;vue-i18n:国际化插件,版本为^7.6.0;vue-markdown:把文章正文的 Markdown 渲染为 HTML。
开发依赖中则包含了contentful-import(用于把导出数据写入新空间)、eslint系列与now(用于部署)。
四、获取 Contentful 配置数据
示例文档强调:要配置并启用一个新空间,必须创建并获取所需的访问令牌。下面按步骤说明。
4.1 创建新的 Space
在 Contentful Web 应用左上角的空间概览区域,点击入口即可创建新空间:
创建新空间对话框
创建完成后,请记下该空间的Space ID,后续配置文件的CTF_SPACE_ID需要用到它。
4.2 创建 Content Management API(CMA)令牌
CMA 令牌用于"写入"侧操作。在顶层菜单进入APIs,再进入Content Management tokens即可创建:
创建 CMA 令牌对话框
注意:导入数据到新空间这一步必须使用 CMA 令牌,因为
contentful-import需要通过管理 API 写入内容模型与内容条目。
4.3 创建 Content Delivery API(CDA)令牌并获取 Space ID
CDA 令牌用于"读取"侧操作。同样在顶层菜单进入APIs,这次进入Content Delivery / Preview tokens创建:
创建 CDA 令牌对话框
复制 CDA 令牌
注意:CDA 令牌用于访问空间中存储的数据,即站点运行时读取文章内容所依赖的凭据。
五、向新空间导入数据
有了 CMA 令牌与 Space ID 之后,就可以把示例附带的内容模型与数据导入新空间。这里使用 Contentful 生态提供的contentful-import工具,它可以把预先导出的数据完整写入指定空间。
由于该工具已被声明为开发依赖(见 package.json 的devDependencies),无需全局安装,直接通过 npm scripts 调用即可。示例文档给出的命令为:
$ npm run import-data -- --space-id YOUR_SPACE_ID --management-token YOUR_MANAGEMENT_TOKEN参数说明:
--:npm 脚本参数透传分隔符。文档特别提示,--用于把 npm scripts 后的参数原样交给实际执行的命令,缺少它会报错;--space-id:目标空间的 ID;--management-token:第 4.2 节创建的 CMA 令牌。
从 package.json 的scripts.import-data可以看到该命令的真实组成:
"import-data": "node ./bin/download-content-model.js && contentful-import --content-file ./data/blog/contentful-export.json"即先执行内容模型下载脚本,再以./data/blog/contentful-export.json为内容文件运行contentful-import,一次性完成"内容模型 + 内容数据"的导入。
六、创建本地配置文件
Contentful 侧配置完成后,需要定义本地运行配置。文档要求将示例根目录下的.contentful.sample.json重命名为.contentful.json,并填入两个(实际是三个)必需值。
6.1 需要配置的键
| 配置键 | 含义 | 填写方式 |
|---|---|---|
CTF_SPACE_ID | 数据所在空间的 ID | 填写你创建的 Space ID |
CTF_CDA_ACCESS_TOKEN | Content Delivery API 令牌,用于拉取数据 | 填写第 4.3 节获取的 CDA 令牌 |
CTF_CMA_ACCESS_TOKEN | Content Management API 令牌,用于获取合法标签 | 填写第 4.2 节获取的 CMA 令牌 |
CTF_PERSON_ID | 作者条目 ID | 示例已预置正确值,无需修改 |
CTF_BLOG_POST_TYPE_ID | 博客文章内容类型 ID | 示例已预置为blogPost,无需修改 |
示例配置文件的完整形态如下(文档同时强调 JSON 不支持注释,实际使用时必须删除注释):
{ // these values are already correct "CTF_PERSON_ID": "15jwOBqpxqSAOy2eOO4S0m", "CTF_BLOG_POST_TYPE_ID": "blogPost", // these values have to be defined by you "CTF_SPACE_ID": "YOUR_SPACE_ID", "CTF_CDA_ACCESS_TOKEN": "YOUR_DELIVERY_ACCESS_TOKEN", "CTF_CMA_ACCESS_TOKEN": "YOUR_MANAGEMENT_ACCESS_TOKEN" }6.2 配置与源码的对应关系
从 nuxt.config.js 的源码可以看到,项目启动时会通过getConfigForKeys一次性读取上述五个键:
const {getConfigForKeys} = require('./lib/config.js') const ctfConfig = getConfigForKeys([ 'CTF_BLOG_POST_TYPE_ID', 'CTF_SPACE_ID', 'CTF_CDA_ACCESS_TOKEN', 'CTF_CMA_ACCESS_TOKEN', 'CTF_PERSON_ID' ])随后这些值被分派到三处使用:
- CDA 客户端:
plugins/contentful.js的createClient用CTF_SPACE_ID与CTF_CDA_ACCESS_TOKEN创建读取客户端; - CMA 客户端:直接用
CTF_CMA_ACCESS_TOKEN创建管理客户端,用于读取文章内容类型、枚举标签集合; - 环境变量:
env块把CTF_SPACE_ID、CTF_CDA_ACCESS_TOKEN、CTF_PERSON_ID、CTF_BLOG_POST_TYPE_ID注入生成期与浏览器上下文,供页面asyncData使用。
七、本地预览站点
配置就绪后,运行:
$ npm run dev该命令会启动开发服务器,站点默认运行在localhost:3000。此时可以验证两件事:数据是否正确从 Contentful 拉取、多语言是否正常工作。
7.1 vue-i18n 的接入方式
该示例通过 Nuxt 插件机制接入 vue-i18n,注册位置在 nuxt.config.js 的plugins数组:
plugins: [ '~/plugins/contentful', '~/plugins/i18n' ]plugins/i18n.js 的核心逻辑如下:
import Vue from 'vue' import VueI18n from 'vue-i18n' const DEFAULT_LOCALE = 'en-US' Vue.use(VueI18n) export default ({ app, req }) => { let locale = DEFAULT_LOCALE if (process.client) { const navigator = window.navigator const languages = navigator.languages || navigator.language || navigator.browserLanguage || navigator.userLanguage locale = languages[0] } else if (req) { locale = req.headers['accept-language'].split(',')[0] } app.i18n = new VueI18n({ locale, fallbackLocale: DEFAULT_LOCALE, messages: { 'en-US': require('~/locales/en-US.json'), 'ja': require('~/locales/ja.json') }, dateTimeFormats: { 'en-US': { short: { year: 'numeric', month: 'short', day: 'numeric' } }, 'ja': { short: { year: 'numeric', month: 'short', day: 'numeric' } } } }) }这段源码揭示了几个关键设计:
- locale 自动探测:客户端优先取
navigator.languages[0],服务端(SSR 场景)取Accept-Language请求头的第一个语言标签,缺省回退到en-US; - fallbackLocale:当某个语言缺少对应文案时,自动回退到
en-US,保证界面永不出现空白键; - 消息与日期格式:英日双语消息分别来自 locales/en-US.json 与 locales/ja.json,并同时注册了两种语言的短日期格式;
- 挂载到 Nuxt 应用:通过
app.i18n暴露给全局,页面中可用$t()翻译文案、用$i18n.locale读取当前语言。
7.2 locale 如何联动 Contentful 内容检索
这是本示例最有价值的一点:界面语言与内容语言由同一个 locale 驱动。以首页 pages/index.vue 为例:
asyncData ({ app, env }) { return Promise.all([ client.getEntries({ 'content_type': env.CTF_BLOG_POST_TYPE_ID, locale: app.i18n.locale, order: '-sys.createdAt' }) ]).then(([posts]) => { return { posts: posts.items } }).catch(console.error) }注意locale: app.i18n.locale——每次请求 Contentful 内容时,都把 vue-i18n 当前的 locale 作为查询参数传入,因此浏览器语言是英文时拉到英文文章,是日文时拉到日文文章。博客详情页 pages/blog/_slug.vue 也采用同样的模式(按fields.slug与app.i18n.locale双重过滤)。而 components/language-header.vue 则用$t('components.language.current', { language: $i18n.locale })把当前语言代码渲染到页面上,作为语言切换的视觉反馈。
7.3 静态生成时的路由预取
部署前若执行nuxt generate,nuxt.config.js 的generate.routes()会在生成期同时调用 CDA 客户端获取全部文章条目、调用 CMA 客户端读取博客内容类型,并把条目 slug 映射为/blog/{slug}、把内容类型上校验的合法标签枚举映射为/tags/{tag},从而保证静态站点覆盖所有动态路由。
八、部署站点到 now
示例文档推荐用now(zeit 提供的静态托管服务)部署。执行:
$ npm run deploy首次运行时会被要求输入邮箱地址并完成确认,之后站点即被发布到云端。从 package.json 可以看到deploy脚本的真实行为:
"deploy": "nuxt generate && now dist"即先执行nuxt generate生成完整静态站点,再把dist目录推送到 now 托管,整个过程无需自建服务器。
九、关键要点与排查提示
- JSON 无注释:配置文件中的
//注释只是文档示意,落地到.contentful.json时必须删除,否则 JSON 解析失败; --透传:npm run import-data必须带--,否则--space-id等参数不会被传给contentful-import;- 三类凭据各司其职:Space ID 定位数据、CDA 令牌读数据、CMA 令牌写/管理数据,三者缺一不可,且不要混淆 CMA/CDA 令牌的用途;
- 语言回退兜底:
fallbackLocale: 'en-US'保证即使某个语言文案缺失也不会出现空白界面; - 生成期与浏览器环境变量:
env块中的配置在nuxt generate与服务端渲染时均可用,页面asyncData中的env参数正是来源于此; - 内容类型 ID 与标签校验:
generate.routes()中通过 CMA 客户端读取内容类型的validations[0].in数组来枚举标签路由,因此标签页路由是"数据驱动"的,内容模型变更后需重新generate。
综上,这份示例文档完整覆盖了"注册 → 建空间 → 取令牌 → 导数据 → 写配置 → 本地运行 → 云端部署"的全链路,而 vue-i18n 在其中扮演的正是"界面多语言 + 内容多语言联动"的核心角色。若要在生产项目中复用该方案,只需替换空间与令牌,并把 locales 下的语言包扩充为你的目标语言即可。
- 前端
- 国际化
【免费下载链接】vue-i18n
:globe_with_meridians: Internationalization plugin for Vue.js
相关推荐
使用 Eleventy 与 Vercel 零配置搭建静态博客:从示例项目到生产部署
使用 Eleventy 与 Vercel 零配置搭建静态博客:从示例项目到生产部署 本指南以当前仓库 examples/eleventy https://lin
CLI后端云原生Element 国际化(i18n)完整实战指南:从语言包配置到 vue-i18n 深度集成
Element 国际化(i18n)完整实战指南:从语言包配置到 vue i18n 深度集成 本文是一份以 Element(Vue.js 2.0 UI Toolk
前端UI组件设计系统在 Vercel 上用 Eleventy 零配置部署博客:从 Markdown 文章到 `_site` 静态站点的完整实践
在 Vercel 上用 Eleventy 零配置部署博客:从 Markdown 文章到 _site 静态站点的完整实践 导读 本文以 Vercel 开源仓库中
CLI后端云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考