PO Editor is a localization plugin for JetBrains IDEs. It helps developers create, edit, validate, and compile GNU gettext translation files directly in the IDE.
Instead of editing .po and .pot files as plain text, you can work with a simple table:
| Identifier | Source text | Translation |
|---|---|---|
button.save |
Save |
Сохранить |
page.title |
Home page |
Главная страница |
The plugin is useful for projects that use gettext, Babel, Flask-Babel, Jinja2, or any other
localization workflow based on .po, .pot, and .mo files.
- Edit
.potranslation files in a three-column table. - Edit
.pottranslation templates in the same table interface. - Create new
.poand.potfiles from the New menu. - Add and delete translation rows from the table editor.
- Attach a
.pottemplate to a.pofile. - Update
.pofiles from a.pottemplate without overwriting existing non-empty translations. - Mark translations that were removed from the template.
- Scan project source code and update a
.pottemplate with new translation keys. - Validate
.posyntax withmsgfmt. - Compile
.pofiles to.mofiles. - Highlight untranslated, fuzzy, completed, source-equal, and removed entries.
- Highlight repeated spaces, tabs, and line breaks in the text fields.
| File type | Purpose | Plugin support |
|---|---|---|
.pot |
Translation template | Table editor, source scan, template update |
.po |
Translation catalog | Table editor, template sync, syntax check, .mo compilation |
.mo |
Compiled binary catalog | Custom file icon |
PO Editor works best with gettext context-based entries:
msgctxt "button.save"
msgid "Save"
msgstr "Сохранить"In this format:
msgctxtis the stable translation identifier.msgidis the source text.msgstris the translated text.
This keeps translation keys stable even when the source text changes.
- Open your JetBrains IDE.
- Go to Settings / Preferences → Plugins → Marketplace.
- Search for PO Editor.
- Click Install.
- Restart the IDE if requested.
You can also install the plugin manually from GitHub Releases.
- Open the repository Releases page.
- Download the plugin ZIP from the latest release assets.
- Do not unzip the archive.
- Open your JetBrains IDE.
- Go to Settings / Preferences → Plugins.
- Click the gear icon.
- Choose Install Plugin from Disk....
- Select the downloaded
.zipfile. - Restart the IDE if requested.
This is useful when the plugin is not yet available on Marketplace, when you need a specific version, or when you want to test a pre-release build.
./gradlew buildPluginThe installable ZIP will be created in:
build/distributions/
Install it with Settings / Preferences → Plugins → Install Plugin from Disk....
- Right-click a directory in the Project view.
- Choose New → POT Translation Template.
- Open the created
.potfile. - Add rows manually or click Update Template to scan the project for translation keys.
- Right-click a directory in the Project view.
- Choose New → PO Translation File.
- Open the created
.pofile. - Click Choose Template and select a
.potfile. - Click Update Translations to add missing rows from the template.
- Fill the translations in the table or in the large text fields below it.
A common workflow:
- Add new translation calls in the source code.
- Open the
.potfile. - Click Update Template.
- Open a
.pofile. - Click Update Translations.
- Translate the new rows.
Existing non-empty translations are preserved.
PO Editor can scan project files and collect static translation keys from calls like:
t("button.save")
i18n("button.save")
translate("button.save")
gettext("button.save")
$t("button.save")
tr("button.save")
_("button.save")
Jinja2 examples:
<title>{{ _('page_title') }}</title>
<p>{{ gettext("page_description") }}</p>Only static string literals are collected. Dynamic keys are ignored because they cannot be safely written to a gettext template.
PO Editor uses msgfmt for syntax validation and .mo compilation.
Install GNU gettext first:
# macOS
brew install gettext
# Debian / Ubuntu
sudo apt install gettextThe plugin looks for msgfmt in:
/opt/homebrew/bin/msgfmt
/usr/local/bin/msgfmt
PATH
Requirements:
- JDK 21
- Gradle Wrapper from this repository
- IntelliJ Platform 2026.1 or newer
Useful commands:
./gradlew test
./gradlew runIde
./gradlew buildPlugin
./gradlew verifyPluginWhat these commands do:
| Command | Purpose |
|---|---|
./gradlew test |
Run tests |
./gradlew runIde |
Start a sandbox IDE with the plugin installed |
./gradlew buildPlugin |
Build the installable plugin ZIP |
./gradlew verifyPlugin |
Check plugin compatibility with JetBrains IDEs |
Project structure:
src/main/kotlin/ru/aksenov/poeditor/
actions/ Toolbar and New-file actions
editor/ Table editor and UI model
parser/ PO parsing and writing
scanner/ Source scanning and template synchronization
- Update
pluginVersioningradle.properties. - Update
CHANGELOG.md. - Update
<change-notes>insrc/main/resources/META-INF/plugin.xml. - Run local checks:
./gradlew clean test buildPlugin verifyPlugin- Commit the release changes.
- Create a Git tag, for example:
git tag v1.0.0
git push origin v1.0.0- Create a GitHub Release for the same tag.
- The release workflow signs and publishes the plugin, then attaches the signed ZIP archive to the GitHub Release.
The main plugin version is defined in:
# gradle.properties
pluginVersion=1.0.0The Gradle build uses this value as the project version:
version = providers.gradleProperty("pluginVersion").get()For a 1.0.0 release, use:
pluginVersion=1.0.0Then create the matching Git tag:
git tag v1.0.0
git push origin v1.0.0The release workflow expects the tag version and pluginVersion to match.
The repository includes GitHub Actions for build checks and release publishing.
See docs/MARKETPLACE.md for Marketplace setup, signing secrets, and the release checklist.
Contributions are welcome. Please read CONTRIBUTING.md before opening a pull request.
For security issues, follow SECURITY.md.
PO Editor is released under the MIT License.