diff --git a/mobile/docs/translations.md b/mobile/docs/translations.md new file mode 100644 index 0000000000..104bd482ce --- /dev/null +++ b/mobile/docs/translations.md @@ -0,0 +1,49 @@ +# Translations + +We use Crowdin for translations, and the `intl` package to load these at +runtime. + +Within our project we have the _source_ strings - these are the key value pairs +in the `lib/l10n/intl_en.arb` file. + +Volunteers can add a new _translation_ in their language corresponding to each +such source key-value to our +[Crowdin project](https://crowdin.com/project/ente-photos-app). + +When a new source string is added, we run a [GitHub workflow](../../.github/workflows/mobile-crowdin-push.yml) +that + +- Uploads sources to Crowdin - So any new key value pair we add in the source + `intl_en.arb` becomes available to translators to translate. + +Every monday, we run a [GitHub workflow](../../.github/workflows/mobile-crowdin-sync.yml) +that + +- Downloads translations from Crowdin - So any new translations that + translators have made on the Crowdin dashboard (for existing sources) will + be added to the corresponding `intl_XX.arb`. + +The workflow also uploads existing translations and also downloads new sources +from Crowdin, but these two should be no-ops. + +## Adding a new string + +- Add a new entry in `lib/l10n/intl_en.arb` (the + **source `intl_en.arb`**). +- Use the new key in code with the `S` class + (`import "package:photos/generated/l10n.dart"`). +- During the next sync, the workflow will upload this source item to Crowdin's + dashboard, allowing translators to translate it. + +## Updating an existing string + +- Update the existing value for the key in the source `intl_en.arb`. +- During the next sync, the workflow will clear out all the existing + translations so that they can be translated afresh. + +## Deleting an existing string + +- Remove the key value pair from the source `intl_en.arb`. +- During the next sync, the workflow will delete that source item from all + existing translations (both in the Crowdin project and also from the + other `intl_XX.arb` files in the repository). diff --git a/mobile/lib/generated/l10n.dart b/mobile/lib/generated/l10n.dart index a76cc59628..b1aedae08c 100644 --- a/mobile/lib/generated/l10n.dart +++ b/mobile/lib/generated/l10n.dart @@ -9945,6 +9945,32 @@ class S { args: [], ); } + + /// `{count, plural, =0 {Added 0 viewer} =1 {Added 1 viewer} other {Added {count} viewers}}` + String viewersSuccessfullyAdded(int count) { + return Intl.plural( + count, + zero: 'Added 0 viewer', + one: 'Added 1 viewer', + other: 'Added $count viewers', + name: 'viewersSuccessfullyAdded', + desc: 'Number of viewers that were successfully added to an album.', + args: [count], + ); + } + + /// `{count, plural, =0 {Added 0 collaborator} =1 {Added 1 collaborator} other {Added {count} collaborators}}` + String collaboratorsSuccessfullyAdded(int count) { + return Intl.plural( + count, + zero: 'Added 0 collaborator', + one: 'Added 1 collaborator', + other: 'Added $count collaborators', + name: 'collaboratorsSuccessfullyAdded', + desc: 'Number of collaborators that were successfully added to an album.', + args: [count], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/mobile/lib/l10n/intl_en.arb b/mobile/lib/l10n/intl_en.arb index 2c7b8701fd..eab99b9c9b 100644 --- a/mobile/lib/l10n/intl_en.arb +++ b/mobile/lib/l10n/intl_en.arb @@ -1363,5 +1363,25 @@ "checkingModels": "Checking models...", "enableMachineLearningBanner": "Enable machine learning for magic search and face recognition", "searchDiscoverEmptySection": "Images will be shown here once processing is complete", - "searchPersonsEmptySection": "People will be shown here once processing is complete" + "searchPersonsEmptySection": "People will be shown here once processing is complete", + "viewersSuccessfullyAdded": "{count, plural, =0 {Added 0 viewer} =1 {Added 1 viewer} other {Added {count} viewers}}", + "@viewersSuccessfullyAdded": { + "placeholders": { + "count": { + "type": "int", + "example": "2" + } + }, + "description": "Number of viewers that were successfully added to an album." + }, + "collaboratorsSuccessfullyAdded": "{count, plural, =0 {Added 0 collaborator} =1 {Added 1 collaborator} other {Added {count} collaborators}}", + "@collaboratorsSuccessfullyAdded": { + "placeholders": { + "count": { + "type": "int", + "example": "2" + } + }, + "description": "Number of collaborators that were successfully added to an album." + } } \ No newline at end of file diff --git a/mobile/lib/ui/sharing/add_participant_page.dart b/mobile/lib/ui/sharing/add_participant_page.dart index 98963bd974..4fadaf1e78 100644 --- a/mobile/lib/ui/sharing/add_participant_page.dart +++ b/mobile/lib/ui/sharing/add_participant_page.dart @@ -239,7 +239,7 @@ class _AddParticipantPage extends State { results.where((e) => e).length; showToast( context, - "Added $noOfSuccessfullAdds ${widget.isAddingViewer ? "viewers" : "collaborators"}", + widget.isAddingViewer ? S.of(context).viewersSuccessfullyAdded(noOfSuccessfullAdds) : S.of(context).collaboratorsSuccessfullyAdded(noOfSuccessfullAdds), ); if (!results.any((e) => e == false) && mounted) {