Skip to content

l10n: clean up locales + consolidate inconsistent source strings (closes #77) - #97

Merged
Jaggob merged 13 commits into
mainfrom
chore/i18n-cleanup
May 27, 2026
Merged

l10n: clean up locales + consolidate inconsistent source strings (closes #77)#97
Jaggob merged 13 commits into
mainfrom
chore/i18n-cleanup

Conversation

@Jaggob

@Jaggob Jaggob commented May 26, 2026

Copy link
Copy Markdown
Collaborator

Closes #77.

Goal of this PR: clean up the existing locale files so the baseline a translation platform will sync against later is consistent. The long-term tooling (translatewiki vs. transifex) is decided post-ether/-transfer; this PR only touches the existing data.

Source-string consolidations (English keys changed)

  • Failed to save settings. — collapses Saving settings failed. and Failed to save settings. (two strings, same meaning).
  • Pending delete retry failed. / Pending delete retry finished. — collapses Lifecycle delete retry failed. / Lifecycle delete retry finished. and unifies the deferred vs pending vs lifecycle terminology around pending.
  • Could not open pad. — collapses the three Unable to open pad. message variants used by the three viewer ErrorMappers. The bare Unable to open pad (no period) stays as the dialog title in EmbedController — title vs. message split is intentional.
  • Retry pending deletes now — renamed from Retry deferred deletes now for terminology consistency.
  • .pad file sync interval (seconds) — clearer than Copy content to .pad file interval (seconds).
  • Delete linked Etherpad pad when .pad file is moved to trash (+ matching hint body) — much clearer than Delete pad on trash about what's pad vs .pad file.
  • Add trusted Etherpad hostnames or HTTPS origins. — uppercase HTTPS to match the body.
  • Hint: Set "authenticationMethod": "apikey" in Etherpad's settings.json. — reads more naturally than the previous reversed ordering.

Locale-file changes

  • Scanned lib/ + templates/ + src/ for actual t() / translate() call sites — 119 unique user-visible strings remaining after the consolidations above.
  • All four locales had ~35–38 orphan entries each (strings the code stopped using, mostly from sidebar / file-action surfaces removed in earlier sprints, plus various Sync status: x variants that were never wired). Dropped them all.
  • DE / DE_DE: brought up to 119/119 by hand. New strings get fresh German; renamed strings carry their old German values forward. A handful of polishes on pre-existing translations:
    • Health checkVerbindungsprüfung (consistent throughout)
    • Query-String und kein Fragment (grammar + technical accuracy)
    • Host-only-Cookie (correct casing for the technical term)
    • Pad sync terminology unified to Synchronisierungs* instead of mixed Sync-*
  • ES / FR: first-pass translations for the 63 strings that were added since their last update (templates, legacy migration, embed flow, admin-settings additions, controller error messages). Native speakers / translation-platform contributors are expected to polish wording later.

All three on-disk formats per locale (.json, .js, .php) are regenerated from a single source-of-truth dict so they stay byte-consistent — historically they had drifted apart on entry ordering and escaping.

Tests

Updated literal-string asserts in the three viewer-ErrorMapper test files where the message text changed. PHPUnit 395/395, vitest 107/107.

Jaggob added 5 commits May 26, 2026 18:16
Scope of #77 reduced to: clean up the existing locale files so the
baseline a translation platform will sync against is consistent.
Long-term tooling (translatewiki vs. transifex) is decided post-
ether/-transfer; this PR only touches the existing data.

What changed in source strings (code side):

- Failed to save settings.: collapses Saving settings failed. and
  Failed to save settings. (two strings, same meaning).
- Pending delete retry failed. / Pending delete retry finished.:
  collapses Lifecycle delete retry failed. /
  Lifecycle delete retry finished. and unifies the deferred vs
  pending vs lifecycle terminology around pending.
- Could not open pad.: collapses the three Unable to open pad.
  message variants used by the three viewer ErrorMappers. The
  bare 'Unable to open pad' (no period) stays as the dialog title
  in EmbedController — title vs. message split is intentional.
- Retry pending deletes now: renamed from
  Retry deferred deletes now for terminology consistency.
- .pad file sync interval (seconds): clearer than
  Copy content to .pad file interval (seconds).
- Delete linked Etherpad pad when .pad file is moved to trash
  (+ matching hint body): much clearer than Delete pad on trash
  about what's pad vs .pad file.
- Add trusted Etherpad hostnames or HTTPS origins.: uppercase
  HTTPS to match the body.
- Hint: Set "authenticationMethod": "apikey" in Etherpad's
  settings.json.: reads more naturally than the previous reversed
  ordering.

What changed in locale files:

- Scanned lib/ + templates/ + src/ for actual t() / translate()
  call sites — 119 unique user-visible strings remaining after
  the consolidations above.
- All four locales had ~35-38 orphan entries each (strings the
  code stopped using over time, mostly from sidebar / file-action
  surfaces removed in earlier sprints, plus the various
  Sync status: x variants that were never wired). Drop them all.
- DE / DE_DE: bring up to 119/119 by hand. The new strings get
  fresh German; the renamed strings carry their old German values
  forward. A handful of pre-existing translations got polished:
  Health check → Verbindungsprüfung (consistent), Query-String
  und kein Fragment (grammar + technical accuracy), Host-only-
  Cookie (correct casing for the technical term), and Pad sync
  terminology unified to Synchronisierungs* instead of mixed
  Sync-*.
- ES / FR: first-pass translations covering the 63 strings that
  were added since their last update (templates, legacy
  migration, embed flow, admin-settings additions, controller
  error messages). Native speakers / translation-platform
  contributors are expected to polish wording later.

All three on-disk formats per locale (.json, .js, .php) are
regenerated from a single source-of-truth dict so they stay
byte-consistent — historically they had drifted apart on entry
ordering and escaping.

Test asserts updated where ErrorMapper strings were referenced
literally (PublicViewer, Embed, Viewer mapper tests).

PHPUnit 395/395, vitest 107/107.
Title and message strings now only differ in the trailing period —
same verb (Could not) across all four locales' translations.

Affects open + create pad: title is the dialog/template heading
(no period), message is the full sentence (with period).

Updated 6 call sites (EmbedController, viewer-main.js,
noviewer.php, comment in EmbedControllerErrorMapper) and the
matching asserts in EmbedControllerErrorMapperTest +
EmbedControllerTest.

PHPUnit 395/395, vitest 107/107.
- Rename English keys: "Pad file" -> ".pad file" in three error
  messages (Could not initialize, Could not resolve, not found),
  matching the .pad-Datei naming used elsewhere.
- DE: fix DNS-hint grammar ("ob er ... aufgelöst werden kann"),
  uppercase HTTPS in the embed-origins label, "Ursprüngliche"
  statt "Originale", and "Zielordner-ID" statt "übergeordnete
  Ordner-ID" for consistency.
- ES/FR: first-pass translations for the renamed keys.
- Rename "Health check" source strings to "Test Etherpad connection"
  family (button label, running, success, failed, failed-with-detail)
  so the user-visible wording matches what's actually tested.
- Snapshot -> "Kopie" / "copia" / "copie" across DE/ES/FR for a more
  user-friendly term (already aligned with "fork the content" copy).
- ES/FR admin-screen polish: drop stray "públicos/publics", fix
  accents, spell out "cadena de consulta" / "chaîne de requête"
  instead of literal "query", and rephrase the external-host
  allowlist label.
The previous scanner regex only matched the t('foo') signature, so all
src/files/* calls using the t(APP_ID, 'foo') form were treated as
orphans and dropped — leaving the public-pad create dialogs, the
file-action label, and the api-client error fallbacks untranslated
in DE/ES/FR.

Tightened the scanner to accept an optional identifier as the first
argument, and re-added the 13 affected keys across all four locales.
Translations for the previously-shipped strings carry over verbatim;
"Creating...", "Public pad from URL" and the remote-snapshot warning
get first-pass translations (translatewiki can polish later).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Jaggob added 8 commits May 27, 2026 12:42
Locale files used to keep whatever insertion order the previous JSON
had, with newly-added keys appended. That made DE / ES / FR
non-overlapping in line numbers and noisy to review side by side.
Sort all four locale catalogs (json/js/php) by key so the same string
lives on the same line everywhere.
de_DE was a byte-for-byte mirror of de. Nextcloud's locale fallback
already maps de_DE users to de.json when de_DE.json is absent, so the
mirror only added drift risk (and would have doubled translatewiki
overhead once it owns the catalogs). We use Du throughout the DE
catalog and have no Sie/Du split that would justify two variants.
Nextcloud's developer manual lists only .json + .js as the required
l10n formats ('you then just need the .json and .js files for a
working localized app'), and the official translationtool only
emits those two. The .php variant is a legacy artefact that no
current code path needs — IL10N reads the JSON. Removing six files
that would only drift if kept.
- ES: fix missing accents in 19 legacy strings (Autenticación,
  política, sincronización, válid*, falló, está, qué, ...);
  drop 'bifurcar' in favor of 'crear una copia independiente'
  and align two related fork/copy phrasings.
- FR: fix missing accents in 17 legacy strings (Vérification,
  cohérence, échoué, Détecté, requête, Clé, paramètres, ...);
  switch 'modifiable' to 'accessible en écriture' for the
  parent-folder-not-writable error; typographic apostrophe in
  the three Open-original strings.
- DE: harmonize progress-message ellipses to ' ...' style (two
  strings already used the leading space, six did not); reword
  the remote-snapshot warning with explicit article and clearer
  outcome ('damit der Inhalt übernommen wird').
- FR: fix remaining unaccented strings (Renseigné automatiquement /
  hôtes / déploiement / l'hôte; hôte invalide; doit être compris) and
  switch the embed-origins label to a typographic apostrophe.
- ES: plural agreement for the pending-delete retry error
  (pudieron, not pudo, since 'las eliminaciones' is plural).
- DE: drop the stray hyphen in 'Test-Fehler' to match the four
  other 'Testfehler' strings.
- FR: unify all 10 'Hint:' translations from 'Indice :' to
  'Conseil :' (more natural French for a UI tip prefix). Switch
  the one imperative 'Ne laissez vide' line to infinitive so all
  four 'Laisser vide / Ne laisser vide' settings hints share the
  same register.
- ES: 'punto final de la API' instead of 'punto de acceso de la
  API' (technical term for endpoint).
'External host allowlist' was ambiguous — sounded like a generic
firewall-style host filter. It's actually the list of Etherpad
server hostnames from which external pads may be linked. Rename
source key to 'External Etherpad host allowlist (optional)' and
update DE/ES/FR accordingly. DE uses the positive phrasing
'Erlaubte externe Etherpad-Hosts (optional)' (drops 'Allowlist'
in favor of the clearer 'Erlaubte ... Hosts').
- docs/i18n.md: rewrite for the new layout (de/es/fr only, .json + .js
  per locale, no .php, no de_DE mirror). Note the translatewiki plan
  and link the Nextcloud l10n docs.
- README: 'Health check' -> 'Test Etherpad connection' to match the
  renamed admin button.
@Jaggob
Jaggob merged commit 2d5300c into main May 27, 2026
10 checks passed
@Jaggob
Jaggob deleted the chore/i18n-cleanup branch June 17, 2026 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

i18n: bring DE to 100% and pick a workflow for FR/ES

2 participants