LingPO Desk

Technical details

How LingPO Desk works with PO catalogs

LingPO Desk grew out of work on multilingual Lingui projects. In the PO-based workflow it was built for, each locale has its own translation catalog.

As more languages are added, comparing corresponding entries one file at a time takes more effort. LingPO Desk brings those entries together in a shared view.

Contexts, plural forms and PO flags stay intact. The same workflow also works with PO files created outside Lingui, provided the project uses the supported catalog structure.

Project structure

Starting with Lingui catalogs

LingPO Desk is designed for a Lingui PO workflow using locales/<locale>/messages.po. In this configuration, each locale has a separate directory containing its catalog:

LingPO Desk identifies the locale from the directory name. locales/de/messages.po becomes the German catalog, locales/fr/messages.po the French catalog, and so on.

The app looks for this structure within the selected project directory, then brings the catalogs it finds into a shared view.

Project directory
locales/
├── en/
│   └── messages.po
├── de/
│   └── messages.po
└── fr/
    └── messages.po

One locale directory, one catalog.

Lingui supports different catalog formats and directory layouts. The PO structure shown here is the workflow LingPO Desk was developed for. PO-based projects outside Lingui can use the same workflow as well, provided their catalogs follow the supported structure.

LingPO Desk deliberately focuses on locales/<locale>/messages.po rather than trying to assign arbitrary PO files from different directory structures automatically. This makes the catalog for each locale unambiguous.

If multiple matching catalogs are found for the same locale, LingPO Desk shows a warning.

You can therefore see which translation files are actually part of the current view.

Bringing catalogs together

Multiple catalogs, one shared view

In this workflow, each locale has its own PO catalog. That separation works well for managing files. When translating or reviewing, however, it is often useful to see the same message across multiple locales.

LingPO Desk turns that perspective around for editing. It matches corresponding entries from the individual files and combines them into shared table rows, placing translations of the same message side by side.

LingPO Desk uses msgid and, where present, msgctxt to match entries.

That distinction matters because the same msgid can appear more than once in a project without referring to the same entry.

For example:

msgctxt "menu"
msgid "Open"
msgstr "Öffnen"

and:

msgctxt "dialog"
msgid "Open"
msgstr "Öffnen"

Both entries use Open as their msgid. Their different contexts refer to different places in the project, so the entries need to be handled independently.

LingPO Desk preserves this distinction when bringing catalogs together.

The resulting view might look like this:

From separate catalogs to a shared table
Source fileslocales/
en/messages.po
msgctxt "menu"
msgid "Open"
msgstr "Open"
msgctxt "dialog"
msgid "Open"
msgstr "Open"
msgctxt "toolbar"
msgid "Save"
msgstr "Save"
de/messages.po
msgctxt "menu"
msgid "Open"
msgstr "Öffnen"
msgctxt "dialog"
msgid "Open"
msgstr "Öffnen"
msgctxt "toolbar"
msgid "Save"
msgstr "Speichern"
fr/messages.po
msgctxt "menu"
msgid "Open"
msgstr "Ouvrir"
msgctxt "dialog"
msgid "Open"
msgstr "Ouvrir"
msgctxt "toolbar"
msgid "Save"
msgstr "Enregistrer"
msgid + msgctxtidentify the row

Shared view

IDContextENDEFR
OpenmenuOpenÖffnenOuvrir
OpendialogOpenÖffnenOuvrir
SavetoolbarSaveSpeichernEnregistrer

Same ID, different context: “menu” and “dialog” remain separate rows.

Each locale supplies its own translation. The combination of msgid and msgctxt places them in the same table row.

The shared view aligns corresponding translation entries across multiple language catalogs.

If an entry is missing from a catalog, its cell stays empty. This makes differences visible that can easily go unnoticed when files are opened individually.

A missing German value appears alongside the existing English and French translations. An entry that occurs in just one language still appears in the table. Identical source text with different contexts remains separate.

The table therefore represents the relationship between catalogs, rather than simply reproducing the contents of one PO file.

Translation states

Three states with different meanings

Untranslated, Fuzzy and Changed may look like three status labels, but they describe different aspects of an entry.

Untranslated

A translation is missing or empty. A plural entry is also incomplete if no plural forms are present or if any existing form is empty.

EnglishGerman
Save

German translation missing

Fuzzy

The PO entry carries the standard fuzzy flag. This flag comes from the catalog itself and remains part of the entry.

#, fuzzy
msgid "Save"
msgstr "Speichern"

Changed

The content or flags have been modified during the current editing session in LingPO Desk.

German · current edits
SichernSpeichern

Changed since loading

Untranslated describes translation completeness. An entry exists, but its translation is not yet complete in at least one language.

Fuzzy is a state recorded in the PO format itself. The flag can indicate that a translation needs review.

Changed refers to your current work in LingPO Desk. It identifies content modified since loading the catalogs or last saving them.

These distinctions let you focus on different tasks. Reviewing missing translations does not require you to work through every fuzzy entry. Reviewing your current edits can be limited to changes made in the session.

This keeps translation completeness, PO status and current edits separate.

Context and plural forms

PO entries contain more than text

A PO entry can contain context, plural forms and flags in addition to source text and its translation.

LingPO Desk takes this structure into account when displaying and editing entries.

Context

A simple entry might look like this:

msgctxt "toolbar"
msgid "Save"
msgstr "Speichern"

msgid identifies the source entry, msgstr contains the translation, and msgctxt specifies the context in which the text is used.

Context can determine whether two entries with the same source text actually belong together.

Plural forms

Plural entries have a little more structure:

msgid "One file"
msgid_plural "%d files"
msgstr[0] "Eine Datei"
msgstr[1] "%d Dateien"

Here, a translation consists of more than one value. msgid_plural and the individual msgstr[n] forms together make up a single plural entry.

LingPO Desk treats these forms as a group, rather than as unrelated pieces of text.

The same principle applies to flags such as fuzzy: they remain associated with their entry and locale.

This lets the app present a consistent table view while preserving the properties of the original PO format.

A shared view across languages

The technical core of LingPO Desk is the relationship between multiple catalogs, not the isolated editing of a single PO file.

The app matches corresponding entries and shows differences between catalogs in the same view.

You can see:

  • which context a message belongs to,
  • which translations are missing,
  • which entries are marked as fuzzy,
  • which entries use plural forms,
  • and which content has changed during the current editing session.

When catalogs for several locales are meant to contain the same set of messages but have diverged over time, the shared view shows those differences without requiring a file-by-file comparison.

A deliberate focus on this workflow

LingPO Desk is not a general translation management system or an editor for arbitrary localization formats. It is intended for reviewing multiple messages.po catalogs together, identifying differences between locales and editing translations in the context of the other languages.

This workflow grew out of work with Lingui, but it is not limited to Lingui projects. What matters is that the PO catalogs use the supported structure.

Rather than covering as many formats and project models as possible, LingPO Desk concentrates on this specific use case.