This guide explains how to add a new language (e.g., French, Portuguese, Japanese) to RPAForge Studio and Python libraries. No deep coding knowledge required - just basic JSON editing.
Supports both:
- Frontend (React UI) — Visual designer, menus, dialogs
- Backend (Python) — Library logging, error messages, operation descriptions
- Node.js and pnpm installed (for frontend changes)
- Python 3.10+ (for backend changes)
- Git account (for contributing translations)
Location: packages/studio/public/locales/
Create a new folder with your language's ISO 639-1 code:
| Language | Folder Name | Example |
|---|---|---|
| French | fr |
packages/studio/public/locales/fr/ |
| Portuguese | pt |
packages/studio/public/locales/pt/ |
| Japanese | ja |
packages/studio/public/locales/ja/ |
Action: Create the folder manually or via command:
mkdir packages/studio/public/locales/[language-code]Copy all 17 JSON files from the English folder:
cp packages/studio/public/locales/en/*.json packages/studio/public/locales/[language-code]/You should have these files:
blocks.json,builtin.json,common.json,credentials.json,database.json,dataframes.json,datetime.json,desktopui.json,errors.json,excel.json,file.json,flow.json,http.json,ocr.json,string.json,variables.json,webui.json
Open each file in a text editor and replace English values with your translation.
For basic terms (common.json):
{
"actions": {
"save": "Save", // → "Сохранить" (Russian) / "Speichern" (German) / "Guardar" (Spanish)
"cancel": "Cancel", // → "Отмена" / "Abbrechen" / "Cancelar"
"ok": "OK" // → "ОК" / "OK" / "Aceptar"
}
}For activity names (library files):
{
"activities": {
"open_workbook": {
"name": "Open Workbook", // → "Открыть книгу" / "Arbeitsmappe öffnen" / "Abrir libro"
"description": "Open an..." // → "Открыть существующий..." / "Öffnen..." / "Abrir..."
}
}
}For parameter labels (activity params):
{
"params": {
"selector": {
"label": "Selector", // → "Селектор" / "Selektor" / "Selector"
"description": "CSS or..." // → "CSS или XPath..." / "CSS oder..." / "CSS o XPath"
},
"timeout": {
"label": "Timeout" // → "Таймаут" / "Zeitlimit" / "Tiempo límite"
}
}
}❌ Don't change:
- JSON structure (curly braces, brackets, commas)
- Key names (
"actions","save","open_workbook","params") - Property names (
"name","description","label","description"inside params) - Unicode control characters
✅ Only change:
- Values (the text after the colon)
The Python RPA libraries (WebUI, DesktopUI, Database, Excel, etc.) use a centralized translation file for common operation messages.
This file contains 348+ translation keys used by Python backend libraries. It's organized by category:
{
"database": {
"connected_to_database": "Connected to database: {database_name}",
"query_returned_rows": "Query returned {row_count} rows",
"transaction_started": "Transaction started"
},
"file": {
"file_not_found": "File not found: {file_path}",
"directory_created": "Directory created: {directory_path}"
},
"webui": {
"page_loaded": "Page loaded: {page_title}",
"navigated_to": "Navigated to: {url}"
}
}Important:
- Keep all placeholder variables like
{database_name},{row_count},{file_path}exactly as they are - These are used for string interpolation in Python code
- Translate only the text around the placeholders
{
"database": {
"connected_to_database": "Подключено к БД: {database_name}",
"query_returned_rows": "Запрос вернул {row_count} строк"
}
}The Python backend automatically detects the language from the LANG environment variable:
# Linux/macOS
export LANG=fr_FR # French
export LANG=de_DE # German
export LANG=pt_BR # Portuguese (Brazil)
# Windows PowerShell
$env:LANG = "fr_FR"Supported languages in Python are defined in packages/libraries/src/rpaforge_libraries/i18n.py:
# Line 61
if lang not in ("en", "ru", "de", "es"): # Add your language code here
lang = "en"If you add a new language, you must update this line to include your language code:
if lang not in ("en", "ru", "de", "es", "fr"): # Added "fr" for French
lang = "en"File: packages/libraries/src/rpaforge_libraries/i18n.py
Find line 61 and add your language code to the supported languages tuple:
# BEFORE:
if lang not in ("en", "ru", "de", "es"):
lang = "en"
# AFTER (example for French):
if lang not in ("en", "ru", "de", "es", "fr"):
lang = "en"File: packages/studio/src/components/Common/SettingsDialog.tsx
Find this section (lines 17-32):
const LANGUAGE_OPTIONS = SUPPORTED_LANGUAGES.map((lang) => ({
value: lang,
label: lang === 'en'
? t('settings.languageEnglish', 'English')
: lang === 'ru'
? t('settings.languageRussian', 'Русский')
: lang === 'de'
? t('settings.languageGerman', 'Deutsch')
: t('settings.languageSpanish', 'Español'),
}));Add your language:
const LANGUAGE_OPTIONS = SUPPORTED_LANGUAGES.map((lang) => ({
value: lang,
label: lang === 'en'
? t('settings.languageEnglish', 'English')
: lang === 'ru'
? t('settings.languageRussian', 'Русский')
: lang === 'de'
? t('settings.languageGerman', 'Deutsch')
: lang === 'es'
? t('settings.languageSpanish', 'Español')
: lang === 'fr'
? t('settings.languageFrench', 'Français') // ← ADD THIS
: t('settings.languageEnglish', 'English'), // fallback
}));File: packages/studio/src/i18n/config.ts
Add your language code to SUPPORTED_LANGUAGES:
export const SUPPORTED_LANGUAGES: Language[] = ['en', 'ru', 'de', 'es', 'fr']; // ← ADD 'fr'File: packages/studio/src/i18n/types.ts
Update the Language type:
export type Language = 'en' | 'ru' | 'de' | 'es' | 'fr'; // ← ADD 'fr'Find the handleSetLanguage function:
const handleSetLanguage = (lang: Language) => { // Already uses Language type from config
setLanguage(lang);
void i18n.changeLanguage(lang);
};No changes needed here - it automatically uses the Language type from config.ts.
-
Build the project:
cd packages/studio pnpm install pnpm build -
Run locally:
pnpm dev
-
Test in UI:
- Open Settings (gear icon or Settings menu)
- You should see your language in the dropdown
- Select it and verify all text is translated
-
Check for missing translations:
- If something shows in English, it means you missed a key
- Use the key names to find and translate the missing phrases
-
Test library translations:
# Set language environment variable export LANG=fr_FR # Replace 'fr' with your language code # Run tests - should use your language cd packages/libraries python -m pytest tests/ -v
-
Verify logs use correct language:
- Run a simple test and check output
- Look for your translated strings in the logs
- If you see English, check that you updated
i18n.py
-
Manual validation (optional):
# Quick Python test import os os.environ["LANG"] = "fr_FR" from rpaforge_libraries.i18n import _ print(_("database.connected_to_database", database_name="test")) # Should print French translation, not English
- Fork the repository
- Create a branch:
feat/translation-[language-code] - Add your changes
- Push and open a PR
If you're not comfortable with Git, you can:
- Compress your locale folder:
tar -czf [language-code].tar.gz packages/studio/public/locales/[language-code]/ - Upload to GitHub Gist or send to project maintainers
| Language | Code | Flag |
|---|---|---|
| Afrikaans | af |
🇿🇦 |
| Arabic | ar |
🇸🇦 |
| Bulgarian | bg |
🇧🇬 |
| Catalan | ca |
🇦🇩 |
| Chinese (Simplified) | zh |
🇨🇳 |
| Chinese (Traditional) | zh-TW |
🇹🇼 |
| Croatian | hr |
🇭🇷 |
| Czech | cs |
🇨🇿 |
| Danish | da |
🇩🇰 |
| Dutch | nl |
🇳🇱 |
| English | en |
🇬🇧 |
| Estonian | et |
🇪🇪 |
| Finnish | fi |
🇫🇮 |
| French | fr |
🇫🇷 |
| German | de |
🇩🇪 |
| Greek | el |
🇬🇷 |
| Hebrew | he |
🇮🇱 |
| Hindi | hi |
🇮🇳 |
| Hungarian | hu |
🇭🇺 |
| Icelandic | is |
🇮🇸 |
| Indonesian | id |
🇮🇩 |
| Italian | it |
🇮🇹 |
| Japanese | ja |
🇯🇵 |
| Korean | ko |
🇰🇷 |
| Latvian | lv |
🇱🇻 |
| Lithuanian | lt |
🇱🇹 |
| Malay | ms |
🇲🇾 |
| Norwegian | no |
🇳🇴 |
| Polish | pl |
🇵🇱 |
| Portuguese | pt |
🇵🇹 |
| Portuguese (Brazil) | pt-BR |
🇧🇷 |
| Romanian | ro |
🇷🇴 |
| Russian | ru |
🇷🇺 |
| Serbian | sr |
🇷🇸 |
| Slovak | sk |
🇸🇰 |
| Slovenian | sl |
🇸🇮 |
| Spanish | es |
🇪🇸 |
| Swedish | sv |
🇸🇪 |
| Thai | th |
🇹🇭 |
| Turkish | tr |
🇹🇷 |
| Ukrainian | uk |
🇺🇦 |
| Vietnamese | vi |
🇻🇳 |
- Ensure you created the folder in the correct location
- Check file names match exactly (lowercase, correct extension
.json)
- You're using
t('key.name')in code - The key
keymust exist in your locale JSON - Use English locale as reference for all available keys
- Check that
SUPPORTED_LANGUAGESarray includes your code - Check that
Languagetype includes your code - Run
pnpm installto rebuild type definitions
If you want to go beyond UI translations, you can also translate the project documentation:
-
Create a new README file:
cp README.md README.[language-code].md # Example: README.fr.md for French -
Translate all content:
- Translate section headers
- Translate descriptions and explanations
- Keep technical names and links intact
- Translate command examples where applicable
-
Add language links to README files:
- In
README.md— add link to new README in header - In your new
README.[lang].md— add links to other languages
Example for French (fr):
[🇬🇧 English](README.md) · [🇷🇺 Русский](README.ru.md) · [🇩🇪 Deutsch](README.de.md) · [🇪🇸 Español](README.es.md) · [🇫🇷 Français](README.fr.md)
- In
-
Key sections to translate:
- Title and subtitle
- Features table
- Architecture description
- Quick Start section
- Libraries table
- Development section
- Roadmap
- Documentation links
- Contributing guidelines
This file is especially important for translators. Consider creating a translated version:
cp HOWTO-TRANSLATE.md HOWTO-TRANSLATE.[lang].md
# Example: HOWTO-TRANSLATE.ru.md for RussianImportant notes:
- Keep the step-by-step structure
- Translate all examples
- Keep command examples in English (code doesn't change)
- Keep file paths in English
- Translate descriptions and explanations
Once you've created translated documentation, add them to the main README:
In README.md Documentation section:
| [Translation Guide](HOWTO-TRANSLATE.md) | Add translations for new languages |
| [Translated Guides](#) | [HOWTO-TRANSLATE.ru.md](HOWTO-TRANSLATE.ru.md) · [HOWTO-TRANSLATE.de.md](HOWTO-TRANSLATE.de.md) || Priority | File | Impact |
|---|---|---|
| High | README.[lang].md |
Main entry point for users |
| High | HOWTO-TRANSLATE.[lang].md |
Helps next translators |
| Medium | docs/getting-started/quick-start.md |
Essential for onboarding |
| Medium | CONTRIBUTING.md |
For contributors in your language |
| Low | ROADMAP.md |
Strategic information |
| Low | CHANGELOG.md |
Historical reference |
- Consistency — Use the same terminology throughout
- Clarity — Translate for understanding, not word-for-word
- Keep Links — Don't translate URLs or file paths
- Preserve Formatting — Keep markdown structure intact
- Technical Terms — Some terms may be better kept in English (JSON, API, etc.)
- Test — Verify translated content reads naturally
- Create folder:
packages/studio/public/locales/pl/ - Copy files:
cp packages/studio/public/locales/en/*.json packages/studio/public/locales/pl/ - Translate all JSON files (
common.json,blocks.json,shared.json, etc.) - Update
packages/libraries/src/rpaforge_libraries/i18n.pyline 61 to includepl - Update
SettingsDialog.tsxlanguage options - Update
i18n/config.tsandi18n/types.tsto includepl - Test both UI (pnpm dev) and backend (pytest with LANG=pl_PL)
- Submit PR
Thank you for contributing translations to RPAForge! 🌍✨