-
Notifications
You must be signed in to change notification settings - Fork 258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sweep through UI strings to internationalize #1148
Conversation
Thanks! This is a lot fewer new strings than I'd expected it to be. I guess we've been pretty good about i18n in new code for the past year or so. I did part of a sweep through
(Stopping there to switch to another task — the remaining code for that sweep is in the |
Marking this for review as I think it would be a good checkpoint. I did a sweep with
As well as the The licenses one can probably be translated with For commits that are local to a file or a class, I use the more specific tag, otherwise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Small comments below.
I see some remaining TODO(i18n)
s that look relevant for #277; would these be easy to do?
- Some in lib/model/compose.dart
- One in lib/notifications/display.dart
- In poll.dart,
TODO(i18n): Localize parenthesis characters
—maybe we want to give this string to translators, rather than do it programmatically? This case seems similar to '#$streamName > $topic' which this PR would give to translators.
assets/l10n/app_en.arb
Outdated
@@ -618,6 +618,14 @@ | |||
"@channelFeedButtonTooltip": { | |||
"description": "Tooltip for button to navigate to a given channel's feed" | |||
}, | |||
"notifChannelConversationLabel": "#{channel} > {topic}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, yeah I guess maybe this could look different in RTL languages, or languages that use a space character other than " "?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. That will be up to the translator to handle then.
assets/l10n/app_en.arb
Outdated
}, | ||
"videoCurrentPositionLabel": "Current position", | ||
"@videoCurrentPositionLabel": { | ||
"description": "The current playback position." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this more descriptive of where in the app this string appears? Same with videoDurationLabel
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renaming this to lightboxVideoCurrentPositionLabel
and updating the description to The current playback position of the video playing in the lightbox
to emphasize that it appears in the lightbox.
assets/l10n/app_en.arb
Outdated
}, | ||
"noEarlierMessages": "No earlier messages", | ||
"@noEarlierMessages": { | ||
"description": "Text to show at the start of a message list if there is no earlier messages." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "if there are no earlier messages"
assets/l10n/app_en.arb
Outdated
"errorOpenLinkTitle": "Unable to open link", | ||
"@errorOpenLinkTitle": { | ||
"description": "Error title when opening a link failed." | ||
}, | ||
"errorOpenLinkDetails": "Link could not be opened: {url}", | ||
"@errorOpenLinkDetails": { | ||
"description": "Error details when opening a link failed.", | ||
"placeholders": { | ||
"url": {"type": "String", "example": "https://chat.example.com"} | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have a naming pattern of fooTitle
and fooMessage
for a pair like this, where one string is for a dialog title and the other is for its message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we use fooDialogMessage
and fooDialogTitle
, but they are not so common (1 and 2 occurences, respectively). Updating the names to use these suffixes instead.
assets/l10n/app_en.arb
Outdated
"description": "Display name for the user themself, to show after replying in an Android notification" | ||
"selfUser": "You", | ||
"@selfUser": { | ||
"description": "Display name for the user themself, to show after replying in an Android notification or on an emoji reaction added by themself." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we keep adding to the description in each new place we use this, it could get pretty long. What do you think about making separate entries for each place in the app that "You" appears? I don't know if that would be helpful for some languages or not.
If keeping as a single entry, maybe keep the description short by not listing any places the string appears, or perhaps saying "for example" and just listing one or two.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having additional context for where each "You" might appear could be helpful, as I find "You" a bit obscure without context, so I'm adding another string.
For the TODOs in For the one in lib/notifications/display.dart, the string to be translated appears in the Android settings menu, outside of the Flutter app, so it seems to be tricky. For |
Oops, I seem to have skipped right past that :) thanks for the bump. Looks like that reason is: "the Yeah, for the quote-and-reply string, we really want something like:
where we get handed the translation for "said" and do the Markdown link syntax around that. In zulip-mobile we have a few places like this: text={{
text: 'Suggestion: <z-link>{suggestedServerUrl}</z-link>',
values: {
suggestedServerUrl: suggestion,
'z-link': chunks => (
<ZulipText
inheritFontSize
style={styles.suggestionTextLink}
onPress={() => handlePressSuggestion(suggestion)}
>
{chunks}
</ZulipText>
),
},
}} but in a quick skim I don't see something like that with the APIs we're using. For this one, perhaps also worth a mention in the followup issue that we might want to translate this into the org's language, not the user's language. |
The other string to translate in
That seems straightforward, and seems appropriate to translate into the user's language rather than the org's language, since it's meant as feedback to the user. Still fine to file as a followup issue :) but it'll be a tiny one. |
Does If it's available to use there in |
90ff1a4
to
652e9a6
Compare
Thanks for the review! The PR has been updated. I also went through the existing i18n TODOs, and the outputs of |
LGTM, thanks! Marking for Greg's review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking care of these! And thanks @chrisbobbe for the previous reviews.
Here's an initial review, on the first few commits:
32caefa display [nfc]: Mention issue for notification channel name's i18n TODO
2523d9c i18n [nfc]: Mention issue for translating styled strings
1494908 app: Translate the "about" page button on popup menu
16211c9 inbox: Make header titles localizable
assets/l10n/app_en.arb
Outdated
"noSubscriptions": "No channels found", | ||
"@noSubscriptions": { | ||
"description": "Text to display when there are no subscribed channels." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"noSubscriptions": "No channels found", | |
"@noSubscriptions": { | |
"description": "Text to display when there are no subscribed channels." | |
"noSubscriptions": "No channels found", | |
"@noSubscriptions": { | |
"description": "Text to display on subscribed-channels page when there are no subscribed channels." |
lib/widgets/inbox.dart
Outdated
@@ -312,7 +314,8 @@ class _AllDmsHeaderItem extends _HeaderItem { | |||
required super.sectionContext, | |||
}); | |||
|
|||
@override String get title => 'Direct messages'; // TODO(i18n) | |||
@override String title(ZulipLocalizations zulipLocalizations) => | |||
zulipLocalizations.recentDmConversationsPageTitle; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make this a separate string — I feel like it's not a given that the heading in this list will be the same as the title atop the other page.
// Strings here left unlocalized as they likely will not | ||
// exist in the settled design. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh, what was this about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was from #397, which followed an old design. The comment is no longer accurate as we localize the strings in the PR. It doesn't seem useful to revise this comment, either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heh, and in fact the comment's prediction was wrong in the first place: the strings haven't changed at all, except for s/streams/channels/ in one of them.
Anyway, that explanation is good — let's put it in the commit message.
lib/widgets/subscription_list.dart
Outdated
child: Text("No channels found", | ||
child: Text(zulipLocalizations.noSubscriptions, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like a mismatch between the name and the actual string. That risks being confusing when looking at the code and thinking about how it relates to the UI. Let's try subscriptionListNoChannels
.
That name starts by scoping where this is found, and then gives the gist of the string's actual content.
c731c83
to
058a684
Compare
Updated the PR, thanks for the review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lib/widgets/profile.dart
Outdated
Text('Could not show user profile.'), | ||
const Icon(Icons.error), | ||
const SizedBox(width: 4), | ||
Text(zulipLocalizations.errorShowUserProfile), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's name this to match the other error strings we have — the name describes the failure, not (or not just) the attempted operation. Here's existing examples:
$ git grep -ohP '^ "error.*?"' assets/l10n/app_en.arb
"errorShowUserProfile"
"errorWebAuthOperationalErrorTitle"
"errorWebAuthOperationalError"
"errorAccountLoggedInTitle"
"errorAccountLoggedIn"
"errorCouldNotFetchMessageSource"
"errorCopyingFailed"
"errorFailedToUploadFileTitle"
"errorFilesTooLarge"
"errorFilesTooLargeTitle"
"errorLoginInvalidInputTitle"
"errorLoginFailedTitle"
"errorMessageNotSent"
"errorLoginCouldNotConnect"
"errorLoginCouldNotConnectTitle"
"errorMessageDoesNotSeemToExist"
"errorQuotationFailed"
"errorServerMessage"
"errorConnectingToServerShort"
"errorConnectingToServerDetails"
"errorHandlingEventTitle"
"errorHandlingEventDetails"
"errorOpenLinkDialogTitle"
"errorOpenLinkDialogMessage"
"errorMuteTopicFailed"
"errorUnmuteTopicFailed"
"errorFollowTopicFailed"
"errorUnfollowTopicFailed"
"errorSharingFailed"
"errorStarMessageFailedTitle"
"errorUnstarMessageFailedTitle"
"errorBannerDeactivatedDmLabel"
"errorBannerCannotPostInChannelLabel"
"errorDialogContinue"
"errorDialogTitle"
"errorInvalidResponse"
"errorNetworkRequestFailed"
"errorMalformedResponse"
"errorMalformedResponseWithCause"
"errorRequestFailed"
"errorVideoPlayerFailed"
"errorMarkAsReadFailedTitle"
"errorMarkAsUnreadFailedTitle"
"errorNotificationOpenTitle"
"errorNotificationOpenAccountMissing"
"errorReactionAddingFailedTitle"
"errorReactionRemovingFailedTitle"
A minimal fix would be errorShowingUserProfile
(it's an error in showing a user profile), or errorCouldNotShowUserProfile
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noting the use of -oh
to show only the matches. That is helpful for finding naming examples.
lib/widgets/message_list.dart
Outdated
return const Text("DMs with yourself"); | ||
return Text(zulipLocalizations.messageListYouWithYourselfTitle); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you do a pass through the rest of the branch to find any other places where the string name doesn't align with its value? Similar to #1148 (comment) above, and to this one.
For this one, let's also make the name parallel the existing examples in the other cases of this switch
— so dmsWithYourselfPageTitle
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
messageListDMsWithOthers
-> dmsWithOthersPageTitle
errorOpenLinkDialogMessage
-> errorCouldNotOpenLinkDialogMessage
errorOpenLinkDialogTitle
-> errorCouldNotOpenLinkDialogTitle
I kept "reactedEmojiSelfUser" as-is:
"reactedEmojiSelfUser": "You",
"@reactedEmojiSelfUser": {
"description": "Display name for the user themself, to show on an emoji reaction added by the user."
},
to match notifSelfUser
:
"notifSelfUser": "You",
"@notifSelfUser": {
"description": "Display name for the user themself, to show after replying in an Android notification"
},
composeBoxLoadingMessage
is left as-is to match composeBoxUploadingFilename
, but maybe we actually want to end both with a Placeholder
suffix?
The remaining string names were unchanged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Replied on specific items in separate threads:
#1148 (comment)
#1148 (comment)
Signed-off-by: Zixuan James Li <[email protected]>
Signed-off-by: Zixuan James Li <[email protected]>
Signed-off-by: Zixuan James Li <[email protected]>
Renamed the "composeBoxUnknownChannelName" string to generalize it. Signed-off-by: Zixuan James Li <[email protected]>
bc450e8
to
5110001
Compare
This descriptions were adapted from [VideoPlayerValue]. Signed-off-by: Zixuan James Li <[email protected]>
Ideally we should implement zulip#1080 for DMs title, but we might switch to showing avatars as the TODO indicated before we work on lists' proper translation. Signed-off-by: Zixuan James Li <[email protected]>
Signed-off-by: Zixuan James Li <[email protected]>
Signed-off-by: Zixuan James Li <[email protected]>
and implement the necessary plumbing to access ZulipLocalizations Signed-off-by: Zixuan James Li <[email protected]>
Thanks! These changes all look good. Since this is marked now as fixing the whole issue, I went back through the same searches described at #1148 (comment) . Here's one hit that also appeared there:
Would you fix that, and also look through the rest of the search results from that point on? Meanwhile I'll merge this but leave out the "Fixes:" for now. |
Signed-off-by: Zixuan James Li <[email protected]>
I went through both queries before the previous push, and didn't find more occurrences since last time. For the licenses one, we discussed here and decided to leave it as-is. We should probably add a comment before that line. |
The '#channel > topic' style strings are not supposed to be translated into different languages as they are Zulip's language of expressing the desintation, not something bound to the English language. See also: zulip#1148 (comment) Signed-off-by: Zixuan James Li <[email protected]>
The '#channel > topic' style strings are not supposed to be translated into different languages as they are Zulip's language of expressing the desintation, not something bound to the English language. The string needs to be re-translated in other languages, as the placeholder is now different. See also: zulip#1148 (comment) Signed-off-by: Zixuan James Li <[email protected]>
The '#channel > topic' style strings are not supposed to be translated into different languages as they are Zulip's language of expressing the desintation, not something bound to the English language. The string needs to be re-translated in other languages, as the placeholder is now different. See also: zulip#1148 (comment) Signed-off-by: Zixuan James Li <[email protected]>
Yep, that should get a comment :-). Thanks. Cross-linking, here's what I found when I went and completed the grep sweep just now: |
The '#channel > topic' style strings are not supposed to be translated into different languages as they are Zulip's language of expressing the desintation, not something bound to the English language. The string needs to be re-translated in other languages, as the placeholder is now different. See also: zulip#1148 (comment) Signed-off-by: Zixuan James Li <[email protected]>
The '#channel > topic' style strings are not supposed to be translated into different languages as they are Zulip's language of expressing the desintation, not something bound to the English language. The string needs to be re-translated in other languages, as the placeholder is now different. See also: zulip#1148 (comment) Signed-off-by: Zixuan James Li <[email protected]>
Partial work for: