You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 57e3ea9
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: ARCHITECTURE.md
+32-4Lines changed: 32 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -614,7 +614,35 @@ The design system provides:
614
614
615
615
`SessionMaterialTheme` installs both the custom tokens and Material 3. Most Compose entry points use `setThemedContent { ... }` so screens can remain thin.
616
616
617
-
## 13. Dependency Injection
617
+
## 13. Localization and Translations
618
+
619
+
UI strings are managed on **Crowdin** (project ID `618696`), not in this repo. This matters because the string resources here are **generated artifacts**, not editable sources.
620
+
621
+
### Source of truth
622
+
623
+
Every `app/src/main/res/values*/strings.xml` — including the base English `values/strings.xml` — plus `NonTranslatableStringConstants.kt` (the `{app_name}`, `{entity_stf_short}`, … substitution values) is generated from Crowdin. **Do not hand-edit these files**; changes are overwritten on the next sync. String source text (English) and translations are both authored/managed on Crowdin.
624
+
625
+
### The sync automation lives in a different repo
626
+
627
+
There is no Crowdin workflow in this repo. The automation is in **`session-foundation/session-shared-scripts`**, workflow `.github/workflows/check_for_crowdin_updates.yml`:
- Downloads from Crowdin, regenerates all `values*/strings.xml` + `NonTranslatableStringConstants.kt` (`crowdin/generate_android_strings.py`), validates via a gradle resource build, then opens/updates a PR using `peter-evans/create-pull-request`.
631
+
- The PR targets the fixed head branch `feature/update-crowdin-translations` → `dev`, opened by the `stfsession` service account. Because the branch is fixed, there is only ever one open translations PR at a time; a re-run updates it in place (unless the previous one was already merged).
632
+
- The same run produces the equivalent PRs for iOS and the desktop localization module.
633
+
634
+
### Approved-only export
635
+
636
+
The download requests translations with `exportApprovedOnly=true` and `skipUntranslatedStrings=true`. Consequently, machine/AI pre-translations are **excluded until a proofreader approves them** in Crowdin — unapproved strings are treated as untranslated and dropped. Approval requires a Proofreader/Manager role on the Crowdin project. (A helper for bulk-approving specific string identifiers lives at `session-shared-scripts/crowdin/approve_strings.py`.)
637
+
638
+
### Shipping a text change
639
+
640
+
1. Edit/add the source strings on Crowdin (new copy usually warrants **new string keys** — reusing a key keeps its now-stale translations, which will resurface as mismatched text).
641
+
2. Approve the translations you want (see above), or they won't export.
642
+
3. Run `check_for_crowdin_updates.yml` and merge the resulting Crowdin PR — this brings the keys into `strings.xml`.
643
+
4. Only then merge any code referencing the new keys (`R.string.<key>` won't compile until the sync has landed them).
644
+
645
+
## 14. Dependency Injection
618
646
619
647
Hilt is the application-wide DI framework.
620
648
@@ -629,7 +657,7 @@ Important modules include:
629
657
630
658
The most important architectural convention here is not just "use Hilt", but "inject long-lived managers plus a manager-scoped coroutine scope and let them expose reactive state."
@@ -640,7 +668,7 @@ The most important architectural convention here is not just "use Hilt", but "in
640
668
641
669
If a bug seems to "happen in the background" but does not fit config, polling, notifications, or Pro, it often lives in one of these auth-aware managers.
642
670
643
-
## 15. End-to-End Flow Summaries
671
+
## 16. End-to-End Flow Summaries
644
672
645
673
### App startup and login
646
674
@@ -695,7 +723,7 @@ User action
695
723
-> reactive flows refresh UI
696
724
```
697
725
698
-
## 16. Practical Notes for new Developers
726
+
## 17. Practical Notes for new Developers
699
727
700
728
For a new developer, the highest-value mental model is:
<stringname="onboardingTosPrivacy">Deur hierdie diens te gebruik, stem jy in tot ons <b>Diensvoorwaardes</b> en <b>Privaatheidsbeleid</b></string>
626
+
<stringname="ongoingAppeal">Nuwe hoop vir {app_name}</string>
627
+
<stringname="ongoingAppealDescription">Toe dit gelyk het of {app_name} dalk sou verdwyn, het jy ingespring.\n\nJou skenkings het die {entity_stf_short} genoeg befondsing gegee om \'n klein span bydraers in staat te stel om die toepassing te onderhou.\n\nOp die oomblik is die fokus daarop om {app_name} veilig, stabiel en aanlyn te hou.\n\nJou skenkings kan help om {app_name} in hierdie kritieke tyd te ondersteun. Bykomende skenkings kan dit moontlik maak om nog ontwikkelaars aan te stel en help om die funksies te lewer wat nodig is om {app_name} vinniger te bevorder.</string>
626
628
<stringname="onionRoutingPath">Pad</string>
627
629
<stringname="onionRoutingPathDescription">{app_name} versteek jou IP deur jou boodskappe deur verskeie Service Nodes in {app_name} se gedesentraliseerde netwerk te stuur. Dit is jou huidige pad:</string>
0 commit comments