Headless CMS 二次开发实践:如何基于 Strapi 实现多语言支持

阅读时长 11 分钟读完

随着 Web 应用的快速发展,前端开发人员的日常工作不再局限于编写页面和样式,越来越多的关注点转向了数据和内容。而 Content Management System (CMS) 的出现,使得 Web 内容的管理与发布变得更加简单和高效。Headless CMS 则更进一步,它不仅可以提供数据存储和管理的功能,还能使得数据的获取和展示更加灵活自由。本文将介绍如何使用 Strapi 这个优秀的 Headless CMS,在二次开发的过程中实现多语言支持。

Strapi 简介

Strapi 是一个开源的 Headless CMS。它基于 Node.js 和 React,并提供了一个可视化的管理界面,用户可以通过界面轻松地创建数据模型,定义字段和关系等。同时,Strapi 支持 GraphQL 和 RESTful API 接口,开发者可以使用自己熟悉的方式来获取和处理数据。此外,Strapi 还提供了丰富的插件和扩展机制,满足不同项目的需求。

多语言支持的必要性

随着互联网时代的到来,人们通过网络获取信息、交流和合作的方式越来越多样化和全球化。对于一个 Web 应用来说,多语言支持已经成为一项基本的需求。无论是企业官网、电商平台还是社交网络,都需要提供多语言版本,以便于吸引更多的用户,扩大市场份额。而这一要求,传统的 CMS 往往比较难以实现,在 Headless CMS 中也需要一些特殊的设计和实现。

Strapi 中的多语言支持设计

在 Strapi 中,多语言支持是通过扩展和插件来实现的。官方提供了一个叫做 strapi-plugin-i18n 的插件,支持多种语言的配置和使用。该插件基于 JSON 文件和模板的方式来管理不同语言之间的差异,并提供了一些工具函数,方便开发者在代码中使用。

具体地说,Strapi 的多语言支持分为两个层次:全局层和局部层。全局层是指整个应用的多语言环境,也就是说,在任何地方都可以使用的翻译。而局部层则是指具体某个数据类型或字段的多语言支持,也就是说,在这个特定的数据类型或字段中才会使用到翻译。下面将分别介绍这两个层次的实现过程。

全局多语言

全局多语言是指一些常见的文案,例如页面标题、按钮文本、提示信息等,它们在整个应用中都存在,且可能出现在多个地方。因此,为了方便管理和维护,通常在一些公共的地方进行配置。在 Strapi 中,可以通过 strapi.config.json 文件来定义全局多语言。

1. 定义语言文件

首先,我们需要在项目中创建一个 i18n 文件夹,用于存放各个语言对应的 JSON 文件。例如,我们创建了一个 en.json 文件和一个 zh-cn.json 文件,分别对应英文和中文。

可以看到,我们在全局层定义了两条翻译记录,分别是标题和欢迎词,它们的 key 值都为 global.title 和 global.welcome。

2. 配置 i18n 插件

接下来,我们需要配置 strapi-plugin-i18n 插件。首先,在 Strapi 项目根目录下执行以下命令:

然后,在项目根目录的 config 文件夹中创建一个 plugins.js 文件,用于配置插件:

-- -------------------- ---- -------
-------------- - -- --- -- -- --
  -------- -
    ------- -
      --------- -------
      ---------------- -
        ----- ---------
      --
      -------- ------ ---------
      --------------- -----
      --------------------- -----
    --
  --
---
展开代码

在这里,我们通过 provider 配置项来设置数据提供器,即 Strapi 会从哪里获取语言配置数据。我们选择了 "json",表示加载本地的 JSON 文件。提供器可选的参数还包括数据库、文件系统等。providerOptions 则指定了实际的语言文件路径,这里是 "./i18n"。locales 数组用于定义支持的语言,fallbackLocale 表示默认语言(如果用户使用的语言不被支持则默认使用该语言),disableDefaultLocale 则表示是否禁用默认语言(为 true 时,将不支持对应 key 值的语言使用默认语言)。

除了以上配置项,i18n 插件还提供了一些有用的 API,例如 strapi.plugins["i18n"].services.i18n.translate() 方法,用于将字符串翻译为对应语言的文字。比如,我们可以在某个 Model 的 hooks 中使用该方法,为某个字段设置翻译值:

-- -------------------- ---- -------
-- -----------------------------

---- --------

---
 - --------- --------- --- --- --------- ------
 --

-------------- - -
  ----------- -
    ------------------ -
      -- -- ---------------- --------
      ------------ - ---------------
        ------
      --------------------------------------------
    --
  --
--
展开代码

这里,在创建 Article 记录时,我们将 content 字段的值设置为了 global.welcome 的翻译值,即根据用户所使用的语言,动态地翻译 "Welcome to my website!",使得页面内容更加灵活。

局部多语言

除了全局多语言,我们有时需要对于某些特定的字段进行翻译。例如,对于一个电商平台来说,商品的名称、描述、价格等字段需要以用户所使用的语言进行展示,以提高用户体验。假设我们已经创建了一个 Product Model,并想对其中的 name、description、price 字段进行翻译,则可以按照以下步骤进行配置。

1. 定义数据模型

首先,在 Strapi 管理界面中创建一个 Product Model,定义 name、description、price 字段。需要注意的是,我们需要为这些字段定义一个 Localized Text 类型,代表着这些字段是支持多语言的。这里我们只添加了英文和中文两个语言,实际项目中可添加更多语言。

2. 配置语言文件

接下来,我们需要为这些字段配置对应的语言文件。在 i18n 文件夹下创建一个 models 子文件夹,并在该文件夹下创建一个 product.json 文件,定义各个字段的翻译值。

-- -------------------- ---- -------
-- ------------------------
-
  --------- -
    ------- -
      ----- -------- ------
      -------- ------
    --
    -------------- -
      ----- -------- -------------
      -------- ------
    --
    -------- -
      ----- --------
      -------- ----
    -
  -
-
展开代码

这里,我们为 Product Model 中的三个字段定义了各自的翻译值,使用了相应的 key 值。需要注意的是,这些 key 值要和 Product Model 中对应字段的 ID 值保持一致。

3. 实现多语言获取

实际开发中,我们需要在代码中动态地读取和展示这些多语言字段。我们可以通过定义一个公共模块,缓存所有的语言文件和 Strapi 插件实例,以方便多个模块的使用。

-- -------------------- ---- -------
-- ----------------
----- ---------- - -----------------------
----- ------------ - -------------------------- -- -------
----- ------------------- - --------------------------------- -- ---
----- ----------------- - -------------------------------- -- -----
----- ------------------------ - -------------------------------------- -- ------
--- ----------- - ---
  ------- - ---

--------------

----- -------- ------------- -
  ----- ------- - ------------------------- -- --------------------
  ----------- - --------

  --- ---- - - -- - - --------------- ---- -
    ----- ------ - -----------
    --- ------------ - ---

    --- -
      -- -----------------
      ----- -------- - ---------------------------------------
      ------------ - ----- -------------------------
        --------------------
        ------
      --
    - ----- ------- -
      -- ----------
      -- --------------------------- -
        ----- -------- - ---------------------------------------
        ------------ - ----- -------------------------
          --------------------
          -----------------
        --
      -
    -

    --------------- - -------------
  -
-

---
 - -----
 - ------ -------- --- -- ---
 - ------ -------- ------ ----
 --
-------- -------------- ------- -
  --- ---- - -------------------- -- --------------------------------
  -- ------- -
    ----- --- ---------- -------- --- ----- -- ----------------
  -
  ------ -----
-

-------------- - -
  ----------
--
展开代码

上面的代码中,我们定义了一个 translate() 方法来进行翻译。该方法接收一个 key 和 locale 两个参数,分别代表着要翻译的字段和当前所使用的语言。它首先会检查当前语言下是否有对应 key 的翻译值,如果有则直接返回,否则,会判断是否禁用默认语言,如果禁用,则会抛出错误;如果未禁用,则使用默认语言的翻译值代替。

我们可以在需要翻译的地方,引入此公共模块,然后通过以下方式来获得多语言的值:

-- -------------------- ---- -------
-- -------------------
----- ---- - ------------------

----- -------- -------------- ------- -
  ----- ------- - ----- --------------------------------- -- ---
  -- ---------- -
    ------ -----
  -
  ------ -
    --- -----------
    ----- ------------------------------------------------------- --------
    ------------ ---------------
      ------------------------------------------------------
      ------
    --
    ------ ------------------------------ ------- - - - - --------------
  --
-
展开代码

在上面的代码中,我们通过 strapi.services.product.findOne() 方法获取到一个 Product 记录,然后将各个字段翻译为用户所使用的语言。需要注意的是,由于我们在 Product Model 中定义了 Localized Text 类型的字段,因此它们实际上存储的是一个对象,包含各种语言的值。在使用这些字段的时候,我们需要根据当前的 locale 属性去取对应的值。

总结

本文介绍了如何使用 Strapi 来实现多语言支持。主要涉及两个层次的设计:全局层和局部层。全局层支持常见的公共文案的翻译;局部层支持对某些特定数据类型或字段进行翻译。具体实现上,我们通过 strapi-plugin-i18n 插件和自定义的代码来完成了这些需求。实践中,我们还可以根据实际情况,定制各种语言技术方案,以充分利用 Strapi 的灵活性和可扩展性。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64ae994a48841e9894abef56

纠错
反馈

纠错反馈