[mob[ Added doc for mobile translations + added 2 new source string… (#4040)
This is my first contribution and I wanted to start with something
'simple'. My goal is to further contribute to the translation of Ente
photos. I am trying to understand that process which is not yet entirely
clear to me, especially when it comes to which files must be (or do not
need to be) generated.
## Description
As a first (small) step, I have:
- created 2 new source strings ('collaboratorsSuccessfullyAdded' and
'viewersSuccessfullyAdded') that replace hardcoded text in the
"add_a_participant" page.
- Created draft of a documentation for translations on mobile app (based
on the doc for web app)
## Tests
Tested on my Pixel 6a
Built with :
- Flutter 3.24.3
- JDK 17.0.2
- Gradle 7.2
## Questions
- I have manually updated the `l10n.dart` file (using existing similar
strings ) but I guess it should be automatically generated from the
`intl_en.arb` file, correct? If so, is it something anyone can do and
can we add the step in the doc?
- Should the other languages be updated as well in that commit, or will
they only be updated via the Github Crowdin action ? Looking at the
existing PR, it seems like they might need to be updated as well in the
commit.
This commit is contained in:
49
mobile/docs/translations.md
Normal file
49
mobile/docs/translations.md
Normal file
@@ -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).
|
||||
26
mobile/lib/generated/l10n.dart
generated
26
mobile/lib/generated/l10n.dart
generated
@@ -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<S> {
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
}
|
||||
@@ -239,7 +239,7 @@ class _AddParticipantPage extends State<AddParticipantPage> {
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user