Gatsby 比 Hexo 更像一个通用框架,关于博客的工具真是全靠社区衬托。Nlvi 迁移遇到了标签云和分类等各种问题,还有一个多语言问题…

找了一圈插件,i18n 大多数方案都是「一个站点同时多语言」,这对一个博客来说没必要啊(相对来说我博文是不是也得写个几份…),想了一圈好像也没必要上react-intl,直接手作一个吧 —— 按照**「好看的皮囊千篇一律」**写一个

但是主题毕竟是要开源的,所以如果有好兄弟萌觉得 i18n 处理不行,自行替换成 gatsby-plugin-i18n 或者 react-intl 就可以了

Context

直接从 react 分出 createContext 方法,直接用

1
2
3
4
5
6
7
8
9
import { createContext } from 'react'

const langContext = createContext({} as ContextInterface)

// 创建上下文后输出 Provider 和 Consumer 还是要的
export const Provider = langContext.Provider
export const Consumer = langContext.Consumer

// ps: 其实 Consumer 用不上...

生成翻译

hexo 版 nlvi 已经有语言文件,所以直接拿过来放到lang文件夹下,然后每个文件通过 yaml2json 转成json,简单一点就不上 yaml 了

大概思路就是:

  • 设定是通过主题的 options 传入 lang 属性,然后 lang 写到 siteMetadata
  • layout 读取语言,传入翻译生成文本,传入 Provider
  • 使用的地方使用 formatMessage 去接

所以也就是接地气且极其简化啥都不考虑保证数据存在版的react-intl。方法可以这么写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export const genTranslate = (lang: string) => {
const _message = require(`@/lang/${lang}.json`)

if (!_message) {
throw Error(`${lang} language json was not found.`)
}

const formatMessage = ({ id, defaultMsg }: FormatMessageType): string =>
// _get 来自 lodash
_get(_message, id) || defaultMsg || ''

const formatter = () => ({ formatMessage, _message })

return formatter()
}

使用翻译

直接用 useContext 去接,2020年该跟风用 hooks 了(大雾

1
export const useIntl = (): ContextInterface => useContext(langContext)

所以这么写的话,只要在 layout 下的组件都可以用这个方式拿到翻译

1
const { formatMessage: t } = useIntl()

这样一来其实跟使用 react-intl 是差不多的,就算日后要改也应该不用动业务代码

所以刚刚那句话还差一半来着?另一半应该是**「糜烂的灵魂(?)凑合对付」**!