Replies: 4 comments 5 replies
|
@dsblank I'm not sure I've seen this work that way you're proposing; might be a cool innovation! Goals 2 & 3, by which translations reach non-English users faster, and give translators an easy way to update translations respectively, are wins. I can see that end-users may feel the urge to update Gramps' built-in translations when they are incorrect, but with the example provided (i.e. Nisan/Nissan) I am wondering if this is a variant that might be added to Gramps for wide-spread use, or a truly a personal preference? Anyway, my general concern is similar to one I mentioned in a related discussion, i.e. there should be sufficient checks in place to avoid situations where an incompatible translation update (if it is forced/automatic) would cause a loss of functionality with an older version of Gramps. In case of Gramps, infrequent releases with string changes make this less likely than with addons. However the concern remains, although it may be that I don't understand the mechanism fully so let me know if it doesn't apply in this case. |
|
For goal 1, allowing users to directly override specific words or phrases allows a highly flexible approach for handling deep dialectal, regional, or personal vocabulary preferences. This is just a display preference for most of the 7,600 strings (still great for individual usability). But for dates it is an important ability to be more flexible in the workflow (eg, entering dates). Of course we will provide strong checks to prevent any crashes or misconfigurations. Regarding using gramps version 6 when weblates moves on to gramps 7, there is no forced or automatic upgrade. But if a user did upgrade translations, they are still tied to a specific message id. If that message id changes (say to use multiple formatted words) this shouldn't cause a problem. Is there a situation that could cause an issue that I am not thinking of? |
Thanks: I updated the project description to include this phrasing. |
Idea: automated pseudo-localization testing to catch overlooked non-translated textWhile testing the override mechanism from PR #2483, I generated a full-catalog override that transforms every string in That surfaced a real gap: most menu items and a lot of static dialog text — anything defined via GtkBuilder XML with This suggests a cheap, ongoing regression test built on the same idea: load every Scope/tradeoffs worth noting:
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Summary
Gramps gets all of its user-visible text — menus, dialogs, calendar month
names, everything — from a translation system, filled in by volunteer
translators for each of the 58+ languages Gramps supports. Today, that
system is entirely one-directional and entirely tied to whatever shipped in
the last release: an individual user has no way to adjust a single word to
their own preference, and the app has no way to benefit from a translation
fix a volunteer made yesterday until the next full Gramps version ships,
months later.
Local Overrides for Translations is a general capability that removes
both restrictions, in three related ways:
Gramps' text with their own preferred wording, permanently, without
touching the installed application. This allows users to directly
override specific words or phrases for a highly flexible approach for
handling deep dialectal, regional, or personal vocabulary preferences.
translation platform (Weblate) for fixes made since the user's
installed version was released, and apply them locally, ahead of the
next full release.
problem while actually using Gramps can contribute that fix back
upstream directly, without a separate trip to the Weblate website. This
is a new, lower-friction workflow for the volunteer translators who
maintain Gramps' language support today.
All three are built on the same small mechanism: a local, personal
translation entry that Gramps checks before falling back to whatever
shipped. The difference between the three is only where the entry came
from and where it's allowed to go — not how it works.
Why it matters
one word" problem — which turns out to affect far more than the Hebrew
calendar spelling that motivated this project (see "Origin," below).
Nothing about it is calendar-specific; it works for any translatable text
in the entire application.
longer has to wait for a release cycle. Community fixes on Weblate can
reach users within days instead of months.
noticing a problem while using the app, then separately opening the
Weblate website, finding the same string again, and fixing it there. This
collapses that into one step — fix it where you saw it, optionally push
it upstream immediately — which should make it easier to keep Gramps'
many translations healthy over time.
Architecture: one mechanism, three uses
The shared foundation: intercepting translation lookups
Every time Gramps needs a piece of text, it asks the translation system
"what's the text for X, in the current language?" The override mechanism
adds one check before that: "is there a local override for X? If so, use
it instead." An override entry looks like this:
{ "language": "en", "context": "Hebrew month lexeme", "msgid": "Nisan", "msgstr": "Nissan" }— language, the original English phrase (
msgid), a disambiguatingcontextwhere needed, and the replacement text (msgstr). This isdeliberately the same shape a translation takes anywhere else in Gramps
(and the same shape Weblate itself uses internally), so an entry can move
between "something a user typed locally," "something pulled from Weblate,"
and "something pushed to Weblate" without any translation or reformatting.
Entries are always tied to a specific language, matching how translation
already works — the same English phrase gets an independent replacement
per language, so one user's preference never bleeds into another
language's experience.
One useful side effect of Gramps' architecture: the same lookup is used
both to display text (turning a stored value into the words you read)
and to understand text you type back in (e.g. turning "Nissan," typed
into a date field, back into the correct month). Because the override
check sits at that one shared point, a single entry fixes both directions
automatically, with no separate work required for user input.
This core mechanism has already been built and directly verified against
the running application: overriding a word changed both what Gramps
displayed and what it accepted as typed input, confirming the basic
approach works, not just in theory.
Mode 1 — Personal overrides
A user keeps a small file,
custom_translations.json, in their personalGramps settings folder — not inside the installed program, so a Gramps
upgrade never touches or overwrites it. Anything in this file is private by
default: it's the user's own permanent choice, and nothing about it is ever
sent anywhere automatically.
Mode 2 — Pulling updates from Weblate
Every installed translation file already records, internally, the date it
was last revised. Using that as a starting point, Gramps can ask Weblate,
for the user's language, "what's changed since then?" and get back just
the differences — typo fixes, improved wording, anything the community has
done since the release the user is running. Accepted updates are kept in a
second file,
weblate_translation_updates.json, separate from personaloverrides, entirely disposable, and only ever fetched when the user
explicitly asks Gramps to check.
Mode 3 — Pushing overrides to Weblate (new)
A translator working in their own language may notice, in the course of
normal use, that a translation is wrong or could read better. Today,
fixing that means leaving Gramps, finding the same string on the Weblate
website, and fixing it there. With this architecture in place, the same
override entry the user would create locally can, if they choose, also be
submitted to Weblate as a real suggestion — using Weblate's own web API,
authenticated as that translator's Weblate account.
This is opt-in per entry, not automatic: a personal override is private
until the user deliberately asks to contribute it, since not every local
tweak someone tries is meant to become the official translation for
everyone. The authentication and submission flow for this direction is not
yet designed in detail — it's included here because the architecture
already supports it naturally (an override entry already looks exactly
like what Weblate expects to receive), and it's a meaningful new workflow
worth building toward, not just a byproduct.
Finding the right phrase to override
Knowing the mechanism exists is one thing; knowing exactly which English
phrase to target is another — Gramps has roughly 7,600 distinct
translatable phrases, far too many to expect a user to already know by
heart. Two complementary sources solve this:
process already extracts every translatable phrase into a template file
as the first step of producing translations at all. Reusing that same
file to ship a small, searchable, offline index — rebuilt automatically
every release — means finding a phrase to override never depends on
being online. This is the reliable fallback the whole feature stands on.
already exposes its data through a public web API, Gramps can search
across every string in the app and see the current official
translation for any language — not just the one the user happens to be
running — live, on request.
Both are used only when the user actively searches or checks for updates;
neither runs automatically in the background (Weblate's public API has a
modest daily request limit for anonymous use, which reinforces this as the
right design regardless).
Keeping the three kinds of entries straight
It matters that personal choices, pulled updates, and pushed contributions
don't get tangled together:
the user explicitly chooses to contribute it upstream.
entirely disposable — safe to re-fetch or discard at any time, since it's
just a local mirror of something that will show up in the next release
regardless.
specifically flagged to share, not the default fate of every override.
Personal overrides and pulled updates live in two separate local files, and
when both apply to the same phrase, the user's own personal choice always
wins — a deliberate customization should never be silently overwritten by
an incoming community fix.
How it all fits together
flowchart TD subgraph Local["On the user's machine"] P[custom_translations.json\npersonal overrides] U[weblate_translation_updates.json\npulled community fixes] end T[Gramps needs to display or\nunderstand a piece of text] --> B{Personal override\nexists?} B -- yes --> R[Use it] B -- no --> D{Pulled update\nexists?} D -- yes --> R D -- no --> S[Use the normal shipped translation] P --> B U --> D OC[Offline phrase catalog\nshipped with Gramps] -.helps find phrase.-> Edit[Editor: search & override] WS[Live search via Weblate] -.helps find phrase.-> Edit Edit -- save --> P WC[Check Weblate for updates\nsince last revision date] --> U P -- user opts in --> Push[Submit to Weblate\nas a suggestion]Origin
This project started from a specific, narrow request: a user wanted to
change the spelling of Hebrew calendar month names (
Nisan→Nissan,Heshvan→Cheshvan) in the English build of Gramps, and discoveredthere was no way to do it — English is the untranslated source language,
so there's no translation file to edit for it. A few heavier fixes were
considered and set aside along the way: adding a whole new "language" for
customization (raises the question of what covers everything not
customized), a new plugin category specific to calendars (solves only
calendars), and editing installed translation files directly (gets wiped
out by every upgrade). The mechanism described above is what those
explorations converged on — and it turned out to generalize well past the
original request, into the three-mode capability described here.
Status
foundation) — confirmed, against the real running application, that a
local override correctly changes both displayed text and what Gramps
accepts as typed input.
search; pulling updates from Weblate (Mode 2); the editor UI a user would
use to search for a phrase and enter an override.
Weblate (Mode 3) — the authentication and submission flow for this
direction still needs to be worked out.
All reactions