#978

Complete European translations and add 24 European languages

OpentranKILLwants to merge intofrom

Description

With the app set to French (or another existing language), many screens still show English: About ("How to use", "No tracking"), most Settings rows ("Run in background", "Proof of work", …), the permission explanations in onboarding, and the hotspot sharing screen. There are two causes: keys missing from the existing values-xx/strings.xml files, and text hardcoded as Kotlin literals.

This PR has five commits:

  1. Move hardcoded UI text into string resources. HotspotActivity, PermissionManager / PermissionExplanationScreen, LocationNotesSheetPresenter, VerificationSheet, InputComponents and AboutSheet (live voice row) now read 44 new keys through stringResource / getString, and existing keys are reused where they already existed. The English text is unchanged. PermissionType keeps its English nameValue for the diagnostics dump and gains a @StringRes titleRes for the UI.
  2. Complete translations for existing European locales. Every missing key is filled in de es fr it nl pl pt ru sv tr uk. Capitalization now follows English (settings rows and bullet lines start with a capital letter). French wording is also cleaned up: informal "tu" throughout, "Preuve de travail", "Système".
  3. Add 24 European languages: be, bg, bs, ca, cs, da, el, et, fi, ga, hr, hu, is, lb, lt, lv, mk, mt, nb, ro, sk, sl, sq, sr. Each has all 607 strings and the CLDR plural forms its language needs, and is listed in locales_config.xml, so it shows up in both the in-app and system language pickers.
  4. Fix plural forms in existing European locales. These bugs already existed upstream and lint flagged them. Russian and Polish defined only one/other, so counts like 2–4 and 5+ used the wrong word form, and Russian printed a literal "1 человек" for 21, 31, … French and Portuguese printed a literal "1 personne" / "1 pessoa", although their one form also covers 0. French, Spanish, Italian and Portuguese gain the CLDR many form.
  5. Use the ellipsis character ("…" instead of "...") in the European files, as French and German already do.

Related to #737. No issue covers the untranslated strings specifically. The companion iOS PR, permissionlesstech/bitchat#1787, adds the same 24 languages to the string catalogs.

How the translations were produced

The translations were written with an AI assistant, not by native speakers. Every file was checked mechanically:

  • every key is present
  • format arguments match the English exactly (%1$s, %2$d, %%)
  • each language has the plural categories CLDR requires (e.g. Polish/Czech few/many, Irish/Maltese two/few/many)
  • Android escaping is valid
  • the first-letter casing matches the English

Native-speaker review is welcome. Corrections only need edits to values-xx/strings.xml.

Risk

Low. Apart from commit 1, the change is resources only. Commit 1 mechanically replaces literals with resource lookups and changes no logic. PermissionType.nameValue is unchanged, so diagnostics output stays in English.

Tests

  • ./gradlew :app:assembleDebug passes
  • ./gradlew testDebugUnitTest passes (612 tests, 0 failures)
  • ./gradlew lintDebug: total findings go from 349 errors / 414 warnings on main to 342 errors / 318 warnings. In the 35 European locales the only findings left are 8 Typos false positives: Norwegian "internett" is the recommended lowercase spelling, and Portuguese "leem" follows the 1990 spelling reform. The remaining MissingTranslation errors are for non-European locales that already lagged behind English, and they now include the 44 keys added in commit 1.
  • LanguageCatalogContractTest passes (locales_config matches the values-* directories)
  • Emulator (API 36): onboarding, About → Info and Settings, the language picker and the chat composer checked in French and Greek; switching language from the in-app picker works

Screenshots

Emulator (API 36), app language set to French, fresh install. Left: main. Right: this branch.

Onboarding: permission explanations (previously hardcoded in Kotlin)

About → Info ("No Tracking", "How To Use" and its rows were missing from values-fr)

About → Settings (setting rows were missing, live push-to-talk was hardcoded, inconsistent lowercase)

New languages: Greek, and the in-app picker listing the added languages

The remaining English line on the Settings card ("Tor connection established to …") comes from the native Tor library and is out of scope.

Not covered (possible follow-ups)

  • CommandProcessor replies (/help, /who, …) are still hardcoded English. Moving them to resources needs a Context passed in, so it's left for a separate PR.
  • Debug-console messages and the native Tor log line stay in English.
  • The wear module is not localized yet.
  • Non-European locales (ar, fa, hi, ja, ko, zh, …) still fall back to English for the keys added here.
  • All-caps section headers are uppercased in code without a locale, so Greek capitals keep their accents ("ΡΥΘΜΊΣΕΙΣ"). That's a small cosmetic fix in the uppercase call.

Checklist

🤖 Generated with Claude Code

Activity

7
chatgpt-codex-connector[bot]8d ago

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code Review✅ Completed 2026-10-22T14:23:49.264858Z23da80bPR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

chatgpt-codex-connector[bot]reviewed8d ago
chatgpt-codex-connector[bot]8d ago

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 23da80b677

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".