-
Notifications
You must be signed in to change notification settings - Fork 664
docs: add Electron integration guide for Lingo.dev CLI #1500
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,377 @@ | ||||||||||||||
| # Electron | ||||||||||||||
|
|
||||||||||||||
| This guide shows you how to integrate Lingo.dev CLI with an Electron application using React and `react-intl` for internationalization. | ||||||||||||||
|
|
||||||||||||||
| ## Prerequisites | ||||||||||||||
|
|
||||||||||||||
| Before you begin, make sure you have: | ||||||||||||||
|
|
||||||||||||||
| - Node.js (v16 or higher) and npm installed | ||||||||||||||
| - Basic knowledge of JavaScript, React, and Electron | ||||||||||||||
|
|
||||||||||||||
| ## Step 1: Create a New Electron Application | ||||||||||||||
|
|
||||||||||||||
| Start by creating a new Electron project. Create a new directory and initialize it: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| mkdir my-electron-app | ||||||||||||||
| cd my-electron-app | ||||||||||||||
| npm init -y | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Install Electron as a dependency: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| npm install electron | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Create a basic Electron main process file `main.js`: | ||||||||||||||
|
|
||||||||||||||
| ```javascript | ||||||||||||||
| const { app, BrowserWindow } = require('electron') | ||||||||||||||
| const path = require('path') | ||||||||||||||
|
|
||||||||||||||
| function createWindow() { | ||||||||||||||
| const win = new BrowserWindow({ | ||||||||||||||
| width: 800, | ||||||||||||||
| height: 600, | ||||||||||||||
| webPreferences: { | ||||||||||||||
| nodeIntegration: false, | ||||||||||||||
| contextIsolation: true | ||||||||||||||
| } | ||||||||||||||
| }) | ||||||||||||||
|
|
||||||||||||||
| win.loadFile(path.join(__dirname, 'renderer/index.html')) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| app.whenReady().then(createWindow) | ||||||||||||||
|
|
||||||||||||||
| app.on('window-all-closed', () => { | ||||||||||||||
| if (process.platform !== 'darwin') { | ||||||||||||||
| app.quit() | ||||||||||||||
| } | ||||||||||||||
| }) | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Update your `package.json` to include the main entry point: | ||||||||||||||
|
|
||||||||||||||
| ```json | ||||||||||||||
| { | ||||||||||||||
| "main": "main.js", | ||||||||||||||
| "scripts": { | ||||||||||||||
| "start": "npm run build && electron ." | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ## Step 2: Set Up React | ||||||||||||||
|
|
||||||||||||||
| Install React and React DOM: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| npm install react react-dom | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| For bundling, we'll use `esbuild`. Install it as a dev dependency: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| npm install --save-dev esbuild | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Create the renderer directory structure: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| mkdir -p renderer | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Create `renderer/index.html`: | ||||||||||||||
|
|
||||||||||||||
| ```html | ||||||||||||||
| <!DOCTYPE html> | ||||||||||||||
| <html lang="en"> | ||||||||||||||
| <head> | ||||||||||||||
| <meta charset="UTF-8" /> | ||||||||||||||
| <title>Electron + Lingo.dev</title> | ||||||||||||||
| </head> | ||||||||||||||
| <body> | ||||||||||||||
| <div id="root"></div> | ||||||||||||||
| <script src="./dist/bundle.js"></script> | ||||||||||||||
| </body> | ||||||||||||||
| </html> | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Create `renderer/index.js`: | ||||||||||||||
|
|
||||||||||||||
| ```javascript | ||||||||||||||
| import React from 'react' | ||||||||||||||
| import { createRoot } from 'react-dom/client' | ||||||||||||||
| import App from './app.js' | ||||||||||||||
|
|
||||||||||||||
| const root = createRoot(document.getElementById('root')) | ||||||||||||||
| root.render(<App />) | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Create `renderer/App.js`: | ||||||||||||||
|
|
||||||||||||||
| ```javascript | ||||||||||||||
| import React from 'react' | ||||||||||||||
|
|
||||||||||||||
| function App() { | ||||||||||||||
| return ( | ||||||||||||||
| <div style={{ textAlign: 'center', marginTop: '100px' }}> | ||||||||||||||
| <h1>Hello!</h1> | ||||||||||||||
| </div> | ||||||||||||||
| ) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| export default App | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Add the build script to `package.json`: | ||||||||||||||
|
|
||||||||||||||
| ```json | ||||||||||||||
| { | ||||||||||||||
| "scripts": { | ||||||||||||||
| "build": "esbuild renderer/index.js --bundle --outfile=renderer/dist/bundle.js --format=iife --platform=browser --target=chrome100 --jsx=automatic --loader:.js=jsx --loader:.json=json", | ||||||||||||||
| "start": "npm run build && electron ." | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Test your setup: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| npm start | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| You should see a window with "Hello!" displayed. | ||||||||||||||
|
|
||||||||||||||
| ## Step 3: Install and Configure react-intl | ||||||||||||||
|
|
||||||||||||||
| Install `react-intl`: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| npm install react-intl | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| Update `renderer/app.js` to use `react-intl`: | ||||||||||||||
|
|
||||||||||||||
| ```javascript | ||||||||||||||
| import React, { useState } from 'react' | ||||||||||||||
| import { IntlProvider, FormattedMessage } from 'react-intl' | ||||||||||||||
| import en from '../i18n/en.json' | ||||||||||||||
| import fr from '../i18n/fr.json' | ||||||||||||||
|
Comment on lines
+160
to
+163
|
||||||||||||||
|
|
||||||||||||||
| const messages = { en, fr } | ||||||||||||||
|
|
||||||||||||||
| function App() { | ||||||||||||||
| const [locale, setLocale] = useState('en') | ||||||||||||||
|
|
||||||||||||||
| return ( | ||||||||||||||
| <IntlProvider locale={locale} messages={messages[locale]}> | ||||||||||||||
| <div style={{ textAlign: 'center', marginTop: '100px' }}> | ||||||||||||||
| <h1> | ||||||||||||||
| <FormattedMessage id="app.greeting" defaultMessage="Hello!" /> | ||||||||||||||
| </h1> | ||||||||||||||
| <button onClick={() => setLocale(locale === 'en' ? 'fr' : 'en')}> | ||||||||||||||
| <FormattedMessage id="app.changeLanguage" defaultMessage="Change Language" /> | ||||||||||||||
| </button> | ||||||||||||||
| </div> | ||||||||||||||
| </IntlProvider> | ||||||||||||||
| ) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| export default App | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ## Step 4: Install and Initialize Lingo.dev CLI | ||||||||||||||
|
|
||||||||||||||
| Install Lingo.dev CLI as a dev dependency: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| npm install --save-dev lingo.dev | ||||||||||||||
|
||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| **Important:** In Electron environments, the standard `npx` commands from the documentation may not work properly. Instead, use the direct Node.js commands. | ||||||||||||||
|
|
||||||||||||||
| Initialize Lingo.dev in your project: | ||||||||||||||
|
|
||||||||||||||
| ```bash | ||||||||||||||
| node ./node_modules/lingo.dev/bin/cli.mjs init | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't how users should be calling the CLI. They should be calling
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes you are right, but the npx command wasn’t running directly inside the Electron environment because Electron doesn’t inherit the full shell context or environment variables where npx is normally available. This can cause failures for users running commands through Electron rather than a regular terminal. "scripts": { This allows them to run: So the docs can show both options, with npx as the standard method and the script-based command as a fallback for environments where npx isn’t directly accessible. |
||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| This command will create an `i18n.json` configuration file. However, you'll need to replace it with the correct configuration for your Electron project. | ||||||||||||||
|
|
||||||||||||||
| Replace the generated `i18n.json` file with the following configuration: | ||||||||||||||
|
|
||||||||||||||
| ```json | ||||||||||||||
| { | ||||||||||||||
| "version": "1.10", | ||||||||||||||
| "locale": { | ||||||||||||||
| "source": "en", | ||||||||||||||
| "targets": ["fr"] | ||||||||||||||
| }, | ||||||||||||||
| "buckets": { | ||||||||||||||
| "json": { | ||||||||||||||
| "include": ["i18n/[locale].json"] | ||||||||||||||
| } | ||||||||||||||
| }, | ||||||||||||||
| "$schema": "https://lingo.dev/schema/i18n.json" | ||||||||||||||
| } | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| This configuration tells Lingo.dev: | ||||||||||||||
| - Your source language is English (`en`) | ||||||||||||||
| - Your target language is French (`fr`) | ||||||||||||||
| - Translation files are located in the `i18n` directory with the pattern `i18n/[locale].json` | ||||||||||||||
|
|
||||||||||||||
| ## Step 5: Authenticate with Lingo.dev | ||||||||||||||
|
|
||||||||||||||
| Before you can generate translations, you need to authenticate and get your (LINGODOTDEV_API_KEY) API key. Run: | ||||||||||||||
|
||||||||||||||
| Before you can generate translations, you need to authenticate and get your (LINGODOTDEV_API_KEY) API key. Run: | |
| Before you can generate translations, you need to authenticate and retrieve your `LINGODOTDEV_API_KEY`. Run: |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent command in troubleshooting section. Line 371 in the troubleshooting section states to use node ./node_modules/lingo.dev/bin/cli.mjs run instead of npx lingo.dev@latest i18n, but throughout the document the command used is node ./node_modules/lingo.dev/bin/cli.mjs run, not i18n. Clarify whether the npx equivalent should be npx lingo.dev@latest run or npx lingo.dev@latest i18n, as this inconsistency may confuse users.
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confusing workflow instruction. The document first instructs users to run lingo.dev run to generate translations (line 243), then immediately says to 'replace' the i18n directory (line 254). This creates confusion about whether users should generate translations first or manually create these files. Consider clarifying that these files should be created before running the translation command, or restructure the steps to have a clearer flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This step is empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry about that! I’ll fix it up right away and update the docs accordingly
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty section with no content. Step 7 only contains a heading with no instructions or explanation. This appears incomplete and should either have content added or be removed entirely.
| Start your Electron application with the following command: | |
| ```bash | |
| npm run start |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a tool that Electron provides for scaffolding a project, rather than these manual steps? (If not, that's fine.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there are tools like Electron Forge and Electron Builder, which many developers use as faster alternatives for scaffolding and packaging.
In this guide, I’ve kept the setup manual to clearly show how lingo.dev integrates with Electron and React-Intl, but we can certainly mention Forge or similar tools as optional faster alternatives if you think that would make the docs more useful.
I can update the docs accordingly if you’d like.