diff --git a/lib/widgets/emoji_reaction.dart b/lib/widgets/emoji_reaction.dart index 3d87b7a8a0a..3107f66f563 100644 --- a/lib/widgets/emoji_reaction.dart +++ b/lib/widgets/emoji_reaction.dart @@ -1,5 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/zulip_localizations.dart'; import '../api/model/model.dart'; import '../api/route/messages.dart'; @@ -143,6 +144,7 @@ class ReactionChip extends StatelessWidget { @override Widget build(BuildContext context) { final store = PerAccountStoreWidget.of(context); + final zulipLocalizations = ZulipLocalizations.of(context); final reactionType = reactionWithVotes.reactionType; final emojiCode = reactionWithVotes.emojiCode; @@ -157,7 +159,7 @@ class ReactionChip extends StatelessWidget { ? userIds.map((id) { return id == store.selfUserId ? 'You' - : store.users[id]?.fullName ?? '(unknown user)'; // TODO(i18n) + : store.users[id]?.fullName ?? zulipLocalizations.unknownUserName; }).join(', ') : userIds.length.toString(); diff --git a/lib/widgets/inbox.dart b/lib/widgets/inbox.dart index 9259c813649..c94a0ae8fdb 100644 --- a/lib/widgets/inbox.dart +++ b/lib/widgets/inbox.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/zulip_localizations.dart'; import '../api/model/model.dart'; import '../model/narrow.dart'; @@ -368,18 +369,21 @@ class _DmItem extends StatelessWidget { @override Widget build(BuildContext context) { final store = PerAccountStoreWidget.of(context); + final zulipLocalizations = ZulipLocalizations.of(context); final selfUser = store.users[store.selfUserId]!; final designVariables = DesignVariables.of(context); final title = switch (narrow.otherRecipientIds) { // TODO dedupe with [RecentDmConversationsItem] [] => selfUser.fullName, - [var otherUserId] => store.users[otherUserId]?.fullName ?? '(unknown user)', + [var otherUserId] => store.users[otherUserId]?.fullName ?? zulipLocalizations.unknownUserName, // TODO(i18n): List formatting, like you can do in JavaScript: // new Intl.ListFormat('ja').format(['Chris', 'Greg', 'Alya', 'Shu']) // // 'Chris、Greg、Alya、Shu' - _ => narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? '(unknown user)').join(', '), + _ => narrow.otherRecipientIds.map((id) => + store.users[id]?.fullName ?? zulipLocalizations.unknownUserName + ).join(', '), }; return Material( diff --git a/lib/widgets/message_list.dart b/lib/widgets/message_list.dart index 29bd244fdb0..01e8057143c 100644 --- a/lib/widgets/message_list.dart +++ b/lib/widgets/message_list.dart @@ -335,12 +335,15 @@ class MessageListAppBarTitle extends StatelessWidget { case ChannelNarrow(:var streamId): final store = PerAccountStoreWidget.of(context); final stream = store.streams[streamId]; + // TODO(i18n): provide translations just as + // 'zulipLocalizations.unknownUserName' for 'unknown channel' final streamName = stream?.name ?? '(unknown channel)'; return _buildStreamRow(context, stream: stream, text: streamName); case TopicNarrow(:var streamId, :var topic): final store = PerAccountStoreWidget.of(context); final stream = store.streams[streamId]; + // TODO(i18n): provide translations for 'unknown channel' final streamName = stream?.name ?? '(unknown channel)'; return _buildStreamRow(context, stream: stream, text: "$streamName > $topic"); @@ -349,7 +352,8 @@ class MessageListAppBarTitle extends StatelessWidget { if (otherRecipientIds.isEmpty) { return const Text("DMs with yourself"); } else { - final names = otherRecipientIds.map((id) => store.users[id]?.fullName ?? '(unknown user)'); + final names = otherRecipientIds.map((id) => + store.users[id]?.fullName ?? zulipLocalizations.unknownUserName); return Text("DMs with ${names.join(", ")}"); // TODO show avatars } } diff --git a/lib/widgets/profile.dart b/lib/widgets/profile.dart index 90f2512042c..fe5a367a470 100644 --- a/lib/widgets/profile.dart +++ b/lib/widgets/profile.dart @@ -290,8 +290,9 @@ class _UserWidget extends StatelessWidget { @override Widget build(BuildContext context) { final store = PerAccountStoreWidget.of(context); + final zulipLocalizations = ZulipLocalizations.of(context); final user = store.users[userId]; - final fullName = user?.fullName ?? '(unknown user)'; + final fullName = user?.fullName ?? zulipLocalizations.unknownUserName; return InkWell( onTap: () => Navigator.push(context, ProfilePage.buildRoute(context: context, diff --git a/lib/widgets/recent_dm_conversations.dart b/lib/widgets/recent_dm_conversations.dart index b8d72e192e2..78be5bff954 100644 --- a/lib/widgets/recent_dm_conversations.dart +++ b/lib/widgets/recent_dm_conversations.dart @@ -93,6 +93,7 @@ class RecentDmConversationsItem extends StatelessWidget { Widget build(BuildContext context) { final store = PerAccountStoreWidget.of(context); final selfUser = store.users[store.selfUserId]!; + final zulipLocalizations = ZulipLocalizations.of(context); final designVariables = DesignVariables.of(context); @@ -107,13 +108,15 @@ class RecentDmConversationsItem extends StatelessWidget { // (should we offer a "spam folder" style summary screen of recent // 1:1 DM conversations from muted users?) final otherUser = store.users[otherUserId]; - title = otherUser?.fullName ?? '(unknown user)'; + title = otherUser?.fullName ?? zulipLocalizations.unknownUserName; avatar = AvatarImage(userId: otherUserId, size: _avatarSize); default: // TODO(i18n): List formatting, like you can do in JavaScript: // new Intl.ListFormat('ja').format(['Chris', 'Greg', 'Alya']) // // 'Chris、Greg、Alya' - title = narrow.otherRecipientIds.map((id) => store.users[id]?.fullName ?? '(unknown user)').join(', '); + title = narrow.otherRecipientIds.map((id) => + store.users[id]?.fullName ?? zulipLocalizations.unknownUserName + ).join(', '); avatar = ColoredBox(color: designVariables.groupDmConversationIconBg, child: Center( child: Icon(color: designVariables.groupDmConversationIcon,