Comments (12)
Thanks for reporting this @lags. I've pushed an update and I'm now seeing the translation files output when npm run dist-windows
(and other platforms should work as well). Please re-open this if you continue to experience problems with this template 😄
from secure-electron-template.
Thanks @pczyzyk. Your code looks good for me and so I pushed a new version of the template with it in there. You should be good now.
from secure-electron-template.
@dotexe0 finally your i18n.mainconfig.js should look like:
const isMac = process.platform === 'darwin'
const isDev = process.env.NODE_ENV === 'development'
const prepend = isMac && !isDev ? path.join(process.resourcesPath, '..') : '.'
i18n.use(backend).init({
backend: {
loadPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.json',
addPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.missing.json',
},`
but the i18n.config.js is a little more tricky:
const isMac = window.api.platform === 'darwin'
const isDev = process.env.NODE_ENV === 'development'
const prepend = isMac && !isDev ? window.api.app.appExtraFilesPath : '.'
i18n
.use(i18nBackend)
.use(reactI18Next.initReactI18next)
.init({
backend: {
loadPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.json',
addPath:
prepend + '/app/localization/locales/{{lng}}/{{ns}}.missing.json',
ipcRenderer: window.api.i18nextElectronBackend,
},
then you need to set those two variables (window.api.platform
and window.api.app.appExtraFilesPath
) in main.js
and preload.js
. Platform is really straightforward, but for appExtraFilesPath I use:
path.join(process.resourcesPath, '..')
Everything is working just fine in both dev and prod with that setup
from secure-electron-template.
@reZach Here's what I did -- it is working as expected:
preload.js
The important part is the last 2 fields (app
& platform
)
...
contextBridge.exposeInMainWorld('api', {
sendIpcMessage: async function (name, requestData) {
return new Promise((resolve) => {
ipcRenderer.send(name, requestData);
ipcRenderer.on(name, (event, responseData) => {
resolve(responseData);
});
});
},
receiveIpcMessage: function (name, callback) {
ipcRenderer.on(name, (event, responseData) => {
callback(responseData);
});
},
i18nextElectronBackend: i18nextBackend.preloadBindings(ipcRenderer),
app: {
appExtraFilesPath: path.join(process.resourcesPath, '..')
},
platform: process.platform
});
i18n.config.js
import i18n from 'i18next';
import * as reactI18Next from 'react-i18next';
import i18nBackend from 'i18next-electron-fs-backend';
// On Mac, the folder for resources isn't
// in the same directory as Linux/Windows;
// https://www.electron.build/configuration/contents#extrafiles
const isMac = window.api.platform === 'darwin'; // <-- field is sourced from preload.js
const isDev = process.env.NODE_ENV === 'development';
const prependPath = isMac && !isDev ? window.api.app.appExtraFilesPath : '.'; <-- field is sourced from preload.js
i18n
.use(i18nBackend)
.use(reactI18Next.initReactI18next)
.init({
backend: {
loadPath: prependPath + '/app/localization/locales/{{lng}}/{{ns}}.json',
addPath: prependPath + '/app/localization/locales/{{lng}}/{{ns}}.missing.json',
ipcRenderer: window.api.i18nextElectronBackend
},
debug: true,
ns: ['common', 'external'],
lng: ['en', 'fr', 'es'],
interpolation: {
escapeValue: false
},
fallbackLng: false // set to false when generating translation files locally
});
window.api.i18nextElectronBackend.onLanguageChange((args) => {
i18n.changeLanguage(args.lng, (error, t) => {
if (error) {
console.warn('t function', t);
console.error('translation error', error);
}
});
});
export { i18n };
The other files were left as-is since they were already working.
from secure-electron-template.
@dotexe0 's solution is fine, but I needed to use some more platform specific paths all over the app, so I used electron-cfg
module and set three parameters in main.js:
const cfg = require('electron-cfg')
async function createWindow() {
(...)
cfg.file('app.json')
cfg.set('appPath', app.getAppPath().replace('/Resources/app.asar', ''))
cfg.set('appExecPath', process.execPath)
cfg.set('appExtraFilesPath', path.join(process.resourcesPath, '..'))
(...)
}
Then I'm setting a window.api.app variable in preload.js
like this:
const appCfg = JSON.parse(fs.readFileSync(pathApp, 'utf8'))
contextBridge.exposeInMainWorld('api', {
i18nextElectronBackend: i18nextBackend.preloadBindings(ipcRenderer),
store: store.preloadBindings(ipcRenderer, fs),
contextMenu: ContextMenu.preloadBindings(ipcRenderer),
app: appCfg,
platform: process.platform,
})
I'm not sure if that is the most efficient way to do that, but it enables me to access appPath
appExecPath
and appExtraFilesPath
throughout the app and at the same time dump values to config file.
from secure-electron-template.
Thanks @pczyzyk and @dotexe0. This new release has these values in the template now, thanks for making this template better for all who use it. I tested this both in dev mode and after packaging the app in Windows & Mac and both changed the language (header/page) successfully.
i18n.config.js
const i18n = require("i18next").default;
const reactI18Next = require("react-i18next");
const i18nBackend = require("i18next-electron-fs-backend").default;
const whitelist = require("./whitelist");
// On Mac, the folder for resources isn't
// in the same directory as Linux/Windows;
// https://www.electron.build/configuration/contents#extrafiles
const isMac = window.api.i18nextElectronBackend.clientOptions.platform === "darwin";
const isDev = window.api.i18nextElectronBackend.clientOptions.environment === "development";
const prependPath = isMac && !isDev ? window.api.i18nextElectronBackend.clientOptions.resourcesPath : ".";
i18n
.use(i18nBackend)
.use(reactI18Next.initReactI18next)
.init({
backend: {
loadPath: prependPath + "/app/localization/locales/{{lng}}/{{ns}}.json",
addPath: prependPath + "/app/localization/locales/{{lng}}/{{ns}}.missing.json",
ipcRenderer: window.api.i18nextElectronBackend
},
debug: false,
namespace: "translation",
saveMissing: true,
saveMissingTo: "current",
lng: "en",
fallbackLng: false, // set to false when generating translation files locally
whitelist: whitelist.langs
});
window.api.i18nextElectronBackend.onLanguageChange((args) => {
i18n.changeLanguage(args.lng, (error, t) => {
if (error) {
console.error(error);
}
});
});
module.exports = i18n;
preload.js
const { contextBridge, ipcRenderer } = require("electron");
const i18nextBackend = require("i18next-electron-fs-backend");
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld("api", {
i18nextElectronBackend: i18nextBackend.preloadBindings(ipcRenderer, process),
});
from secure-electron-template.
@reZach for Darwin it is still not working correctly after npm run dist-mac
. All files are there inside the package, but i18next does not seem to load them correctly. For npm run dev
seems to be working just fine though.
That is probably because extraFiles are being copied to a slightly different location on Mac: https://www.electron.build/configuration/contents#extrafiles
from secure-electron-template.
@pczyzyk good catch. It would appear as app/localization/i18n.config.js
and app/localization/i18n.mainconfig.js
need to be updated in the case where the app is run from the generated application.
In these files, can you prepend "Contents" to see if this works? If it does, then I imagine a solution needs to be thought of to handle MacOS post-build, and all other scenarios that work today. I'm not yet sure what the solution would be..
backend: {
loadPath: "./Contents/app/localization/locales/{{lng}}/{{ns}}.json",
addPath: "./Contents/app/localization/locales/{{lng}}/{{ns}}.missing.json",
ipcRenderer: window.api.i18nextElectronBackend
},
from secure-electron-template.
@reZach that was not that trivial.
It seems that on Mac you need to provide a full path in order to reach the files in Contents folder.
So I did some quick fixes in app/localization/i18n.config.js
and app/localization/i18n.mainconfig.js
eg. i18n.mainconfig.js
:
const isMac = process.platform === 'darwin';
const isDev = process.env.NODE_ENV === 'development';
const prepend = isMac && !isDev ? path.join(process.resourcesPath, '..') : '.';
i18n.use(backend).init({
backend: {
loadPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.json',
addPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.missing.json',
},
I confirm that this solution is working fine on Mac dist
from secure-electron-template.
@reZach @pczyzyk I see it working in development mode, but not in the production build and it's pretty straightforward to replicate. Just running npm run dist-mac
and running the app will show the Language menu working with i18n changes but selecting a different language will not change the language in the window (i.e. 'Hello' -> 'Hallo').
I believe it's because the logic that leverages process.resourcePath
and process.platform
is not available to the React application, so those values are undefined. These process
values are available however to electron, so it makes sense that the menu portion works.
// app/localization/i18n.mainconfig.js
const isMac = process.platform === 'darwin'; <-- value present in process -- OK
const isDev = process.env.NODE_ENV === 'development'; <-- value present in process -- OK
const prepend = isMac && !isDev ? path.join(process.resourcesPath, '..') : '.'; <-- value present in process -- OK
i18n.use(backend).init({
backend: {
loadPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.json',
addPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.missing.json',
},
// app/localization/i18n.config.js
const isMac = process.platform === 'darwin';
const isDev = process.env.NODE_ENV === 'development';
const prepend = isMac && !isDev ? path.join(process.resourcesPath, '..') : '.';
console.log(process.platform) // <-- undefined
console.log(process.resourcePath) // <-- undefined
i18n.use(backend).init({
backend: {
loadPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.json',
addPath: prepend + '/app/localization/locales/{{lng}}/{{ns}}.missing.json',
},
Am I missing something?
from secure-electron-template.
@pczyzyk Can you share your preload.js how you helped @dotexe0? I'd like to somehow incorporate your changes into the template/proper location so this change can be used by others.
from secure-electron-template.
I re-opened this issue to keep note that this is something I need to fix in the template, thanks!
from secure-electron-template.
Related Issues (20)
- integrating react v18 be default HOT 2
- React Devtools won't load in packaged app? HOT 5
- NPM Audit Fix --Force Breaks Template HOT 1
- How to update packges? HOT 1
- typescript imports should just work in vscode HOT 2
- How I can install Tailwind?
- Make a Worker on button click HOT 1
- Deploying an auto-updating after build HOT 1
- Requesting a Vue example, instead of React
- Requesting a SQLite example, instead of JSON
- Cannot use import statements outside a module HOT 1
- Is it ok to Import libraries like SortableJs directly into Renderer? or should it be done through preload as well? HOT 2
- electron + webpack + angular HOT 1
- how to access the .env variables ?
- Unable to use react-apexcharts with the template HOT 1
- Old electron & 28 vulnerabilities HOT 2
- Not secure app, able to content of files after building app HOT 1
- Browser route not working from index.tsx file by npm run prod
- App opens only when VSCode is started first time
- Protocol Path Sanitisation
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from secure-electron-template.