The Sync page gives each folder one card with its state, a Synced / Online only switch and a menu for the rest; switching either way asks first and the download prompt shows the free space on the disk. Enabling, disabling and restarting the Proton Drive service ran systemctl on GTK's main thread and froze the window. They now run in the background, and every Retry button goes through one shared restart helper. Ten icons are bundled under resources/icons for glyphs no stock theme has or that read ambiguously (sync, share, people, link, menu, map and so on). A new test fails when the app or search prompt asks for a symbolic icon that is neither bundled nor on a list checked against Adwaita 50, libadwaita and GTK, or when a bundled icon is missing from the resource manifest. The tray's sync icon, which Adwaita 50 no longer ships, is now view-refresh. Wording follows one glossary, recorded in docs/TRANSLATING.md: "Proton Drive service" instead of "mount service" or "daemon", "Online only" instead of "On-demand", "Proton Drive folder" instead of "mountpoint". Dialog headings and buttons use title case and page titles match the sidebar. Dates go through one formatter (app/dates.rs) and sizes through i18n::human_bytes, and the cache label is translated. The status tick stops while the window is hidden or minimized and runs every fifth tick while it is unfocused, refreshing as soon as it gains focus. "Sync complete" is announced only for large batches and only when the window isn't focused. Smaller fixes: Empty Trash hides when there is nothing to empty, copy buttons confirm with a check mark, the sidebar status spins until the first report, and Photos moves Import and Find Duplicates into a menu beside a labelled Select toggle. All catalogs are updated and complete.
4.9 KiB
Translating Proton Drive for Linux
The desktop app (pdfs-app), the tray (pdfs-tray) and the search prompt (pdfs-prompt) are
translated with GNU gettext in the pdfs text domain. The pdfs command-line tool and the daemon's
own messages stay in English, because scripts parse their output.
US English is the source language. The shipped catalogs are listed in po/LINGUAS:
German, British English, Spanish, French, Italian, Dutch, Polish and Brazilian Portuguese.
Picking a language
The apps follow the system locale (LANGUAGE, LC_ALL, LC_MESSAGES, LANG). Preferences →
General → Appearance → Language overrides that for the app, the tray and the prompt. The choice is
stored as language in config.json and takes effect the next time they start.
Layout
| Path | Purpose |
|---|---|
crates/pdfs-gui/src/i18n.rs |
Locale setup and the gettext, gettext_f, ngettext_f, pgettext and gettext_noop helpers |
po/POTFILES.in |
Sources that xgettext scans |
po/pdfs.pot |
The template, generated from the sources |
po/<lang>.po |
One catalog per language |
po/update.sh |
Regenerates the template and merges it into every catalog |
po/build.sh <localedir> |
Compiles the catalogs to <localedir>/<lang>/LC_MESSAGES/pdfs.mo |
Updating an existing translation
-
Run
po/update.sh. It regeneratespo/pdfs.potand merges new and changed strings into each catalog, marking changed onesfuzzy. -
Edit
po/<lang>.powith a PO editor (Poedit, Lokalize, GNOME Translation Editor) or a text editor. Translate the empty entries and review everyfuzzyone, then remove itsfuzzyflag. -
Check the catalog with
msgfmt --check --statistics -o /dev/null po/<lang>.po. -
Try it from the source tree:
po/build.sh target/locale PDFS_LOCALEDIR=target/locale LANGUAGE=<lang> cargo run -p pdfs-gui --bin pdfs-app
Adding a language
- Add the code (for example
svorpt_PT) topo/LINGUAS, keeping the list sorted. - Run
po/update.sh. It createspo/<lang>.pofrom the template withmsginit. - Fill in the
Plural-Formsheader ifmsginitdid not, and translate the catalog. - Add the code and the language's own name to
LANGUAGESincrates/pdfs-gui/src/i18n.rs, so the Preferences picker offers it. - Add
GenericName[<lang>],Comment[<lang>]andKeywords[<lang>]lines to the two desktop files inpackaging/.
cargo test -p pdfs-gui checks that every language in the picker has a catalog, that
po/POTFILES.in lists every source file that calls gettext, and that every catalog passes
msgfmt --check.
Rules for translators
- Keep every
{placeholder}from the English text. You may move it, but not rename or drop it.msgfmt --checkrejects a catalog where they differ. Plural forms keep{n}in every form. - Read the
#.translator comments above an entry. They explain placeholders and date formats. - Date entries such as
%b %earestrftimeformats for GLib'sDateTime::format. Translate them into the order and separators your language uses, not into literal dates. - A
msgctxtsuch asverborcolumntells you which meaning of a short word is meant. - Keep product names as they are: Proton Drive, Proton, Google Takeout.
- Use the same term for the same thing across the catalog, and follow the terminology of your desktop (GNOME or KDE) for common actions such as Trash, Preferences and Cancel.
- The English UI uses one term per concept. Pick one translation for each and keep it:
Concept English term The root of the user's Drive My files The background service Proton Drive service (never "daemon" or "mount") A folder with a full copy on this computer Synced folder A folder whose files download when opened Online-only folder A single file kept on this computer Available offline A single file that is not on this computer Online only Where My files appears on disk Proton Drive folder Stop syncing a folder Stop syncing Two versions of one file Conflict
Rules for developers
- Wrap every user-visible GUI string:
gettext("Move to Trash"). - Never build a sentence from translated pieces or with
format!. Use named placeholders:gettext_f("Moved {name} to Trash", &[("name", &name)]). - Counts use
ngettext_f("{n} item", "{n} items", count, &[]);{n}is filled in for you. - Give short, ambiguous words a context:
pgettext("verb", "Open"). - Mark labels in
consttables withgettext_noopand translate them where they are shown. - The message id must be a single string literal on one line, since
xgettextreads literals only. - Add a
// Translators:comment on the line above a call whose meaning is not obvious. - Do not translate log messages, CLI output, action or icon names, or values the daemon sends back.
- Run
po/update.shafter changing strings and commit the updated template and catalogs.