前言:i18next是可以应用于electron框架中的一个i18n工具框架,用于js应用程序

一、在electron项目中导入i18next

npm install i18next

安装完成后,使用require引入

const i18n = require('i18next');

二、i18next针对单个DOM元素进行语言切换

1.在main.js中封装初始化函数,根据配置的参数进行i18next的初始化,并返回初始化结果

// 初始化 i18next
const initI18next = () => {
  return i18n.init({
    fallbackLng: 'en', // 默认回退语言
    resources: {
      en: {
        translation: require(path.join(__dirname, 'language/en.json'))
      },
      zh: {
        translation: require(path.join(__dirname, 'language/zh.json'))
      }
    },
    lng: 'zh', // 初始语言
    interpolation: {
      escapeValue: false,
    },
  });
};
参数含义
lng设置初始语言码,优先调用该语言码的json语言文件
fallbackLng回退语言码,若初始语言码设置失败,则默认回退到该语言码进行设置
resources各语言码对应的json语言文件存储路径
interpolation定义插值的自定义行为
escapeValue控制是否对插值表达式中的变量值进行HTML转义

不同语言json文件举例

//language/zh.json
{
    "top": "顶部",
    "bottom":"底部",
    "first": "第一条",
    "second":"第二条"
}

//language/en.json
{
    "top": "top",
    "bottom":"bottom",
    "first": "first",
    "second":"second"
}

2.main.js中等待electron应用初始化完成后(包括各个模块的引入)进行i18next的初始化

//app ready处进行初始化
app.whenReady().then(() => {
  //检查初始化完成
  initI18next().then(() => {
    console.log('i18next is ready to use.');
  }).catch((err) => {
    console.error('Error initializing i18next:', err);
  });
  // createWindow()
  createLayoutWindow()
})

3.在main.js中监听渲染进程的语言切换请求,调用i18n.t()函数传入要操作的key,i18n会根据目前的语言码找到对应的json文件,从文件中读出key对应的value并返回

// 处理语言切换请求
ipcMain.handle('i18next', (event, key) => {
  return i18n.t(key);
});

4.electron中做到上下文隔离,在preload中暴露接口,让渲染进程能够调用

contextBridge.exposeInMainWorld('layoutFromMain', {
  i18next:(key)=>ipcRenderer.invoke('i18next', key)
})

5.渲染进程中,调用该接口并进行DOM更新,该翻译函数可以在需要的地方调用即可,比如绑定到某个按钮上等

注意:这里获取DOM使用的方法是获取ID,第6点会讲到通过获取data-i18n属性来获取DOM元素

const getTranslation = async (key) => {
    try {
        const translation = await window.layoutFromMain.i18next(key);
        // 使用返回的文本更新 DOM 
        document.getElementById(key).textContent = translation;
    } catch (error) {
        console.error('Error fetching translation:', error);
    }
}

6.使用data-i18n属性来获取DOM属性,更新一下第5小点中的渲染页面的getTranslation函数,这里通过获取data-i18n属性符合的元素来进行更改

// DOM语言切换函数
const getTranslation = async (key) => {
    try {
        const translation = await window.layoutFromMain.translate(key) 
        const element = document.querySelector(`[data-i18n="${key}"]`)
        if (element)
            element.textContent = translation
    } catch (error) {
        console.error('Error fetching translation:', error)
    }
}

在html中,使用data-i18n属性方式如下

<div id="top" data-i18n="top">top</div>

完成以上步骤后,可以在渲染页面中通过getTranslation()函数传入想要切换语言的元素

三、i18next针对整个渲染页面进行批量元素语言切换

  1. 渲染页面中,需要进行语言切换的DOM元素均需要添加data-i18n属性
  2. 封装批量元素语言切换函数translatePage,在该函数中,首先选择所有需要的元素,并使用遍历方法挨个进行替换
async function translatePage() {
    const elements = document.querySelectorAll('[data-i18n]')// 选择所有带有 data-i18n 属性的元素
    for (const element of elements) {
        const key = element.getAttribute('data-i18n') // 获取 data-i18n 属性的值
        const translation = await window.layoutFromMain.translate(key)
        element.textContent = translation // 更新元素的文本内容
    }
}
  1. 在渲染页面中监听DOMContentLoaded事件,一旦网页装载完毕,调用translatePage来进行语言切换。切换的语言由main.js中配置的语言码决定,下一小节会介绍如何切换语言码并重新刷新页面
document.addEventListener('DOMContentLoaded', translatePage);

四、切换语言码并刷新渲染界面

  1. 在preload中暴露IPC通信接口,这里直接在里面新增一个changeLanguage接口函数
contextBridge.exposeInMainWorld('layoutFromMain', {
  i18next:(key)=>ipcRenderer.invoke('i18next', key),
  changeLanguage: (language) => {
    ipcRenderer.invoke('changeLanguage', language)
  },
})
  1. main.js中监听该通信
ipcMain.handle('changeLanguage', async (event, languageCode) => {
  try {
    await i18n.changeLanguage(languageCode)
    //console.log('change success, language : '+i18n.language );//调试
    return true
  } catch (error) {
    console.error('Failed to change language:', error)
    return false;
  }
});
  1. 在渲染页面中使用changeLanguage函数并传入语言码(注意:这个changeLanguage函数不是preload中的changeLanguage函数,这个是属于渲染进程中的函数),等待主进程语言切换完成后,重新加载该渲染页面,通过上一小节提到的函数translatePage来批量对元素进行语言切换
async function changeLanguage(languageCode) {
    try {
        await window.layoutFromMain.changeLanguage(languageCode);
        location.reload();
    } catch (error) {
        console.error('Change language failed:', error);
    }
}
  1. 通过将hangeLanguage函数绑定到按钮或其他元素上来触发整个渲染页面更新的效果,达到实现翻译的功能

疑难杂症

1.菜单栏设置了拖动,无法点击,导致无法收起下拉菜单

注意分辨以下提到的内容

菜单栏:指自定义窗口菜单栏

语言切换下拉菜单(下拉菜单):指语言切换功能中选择不同语言的下拉选择框

菜单栏设置了-webkit-app-region: drag样式,导致菜单栏只能拖动无法点击。而下拉菜单逻辑为,打开下拉菜单后,点击其他非下拉菜单的地方都能收起下拉菜单。但菜单栏设置了drag样式,所以点击时无法收起下拉菜单。

**解决办法:**在打开下拉菜单时,去除菜单栏的drag样式,这样除开下拉菜单,其他地方进行点击都能够收起下拉菜单。在收起下拉菜单同时,将no-drag样式重新加载到菜单栏上,让拖拽功能恢复。

// 点击下拉菜单按钮时切换下拉菜单的显示
langBtn.addEventListener("click", function (event) {
    event.stopPropagation(); // 阻止事件冒泡
    langDropdown.classList.toggle("show");
    titleBar.style.WebkitAppRegion = 'no-drag';
})

//点击下拉菜单外部时隐藏下拉菜单
document.addEventListener("click", function (event) {
    // 检查点击事件是否在下拉菜单或按钮之外
    var isClickInsideDropdown = langDropdown.contains(event.target);
    if(!isClickInsideDropdown){
        langDropdown.classList.remove("show");
        titleBar.style.WebkitAppRegion = 'drag';
    }

})
文章作者: keeshow
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 keeshow
默认分类 Electron
喜欢就支持一下吧