electron框架中语言切换(翻译功能)
前言: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针对整个渲染页面进行批量元素语言切换
- 渲染页面中,需要进行语言切换的DOM元素均需要添加data-i18n属性
- 封装批量元素语言切换函数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 // 更新元素的文本内容
}
}
- 在渲染页面中监听DOMContentLoaded事件,一旦网页装载完毕,调用translatePage来进行语言切换。切换的语言由main.js中配置的语言码决定,下一小节会介绍如何切换语言码并重新刷新页面。
document.addEventListener('DOMContentLoaded', translatePage);
四、切换语言码并刷新渲染界面
- 在preload中暴露IPC通信接口,这里直接在里面新增一个changeLanguage接口函数
contextBridge.exposeInMainWorld('layoutFromMain', {
i18next:(key)=>ipcRenderer.invoke('i18next', key),
changeLanguage: (language) => {
ipcRenderer.invoke('changeLanguage', language)
},
})
- 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;
}
});
- 在渲染页面中使用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);
}
}
- 通过将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';
}
})