diff --git a/packages/stream_chat_flutter/example/lib/main.dart b/packages/stream_chat_flutter/example/lib/main.dart index de2433ab..d643dfea 100644 --- a/packages/stream_chat_flutter/example/lib/main.dart +++ b/packages/stream_chat_flutter/example/lib/main.dart @@ -70,6 +70,10 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) => MaterialApp( theme: ThemeData.light(), darkTheme: ThemeData.dark(), + supportedLocales: const [ + Locale('en'), + Locale('hi'), + ], localizationsDelegates: const [ GlobalStreamChatLocalizations.delegate, GlobalCupertinoLocalizations.delegate, diff --git a/packages/stream_chat_flutter/lib/src/channel_info.dart b/packages/stream_chat_flutter/lib/src/channel_info.dart index e9c2b7c9..4e860745 100644 --- a/packages/stream_chat_flutter/lib/src/channel_info.dart +++ b/packages/stream_chat_flutter/lib/src/channel_info.dart @@ -84,8 +84,8 @@ class ChannelInfo extends StatelessWidget { ); } else { alternativeWidget = Text( - context.translations.userLastOnlineText + - Jiffy(otherMember.user?.lastActive).fromNow(), + '${context.translations.userLastOnlineText} ' + '${Jiffy(otherMember.user?.lastActive).fromNow()}', style: textStyle, ); } diff --git a/packages/stream_chat_flutter/lib/src/channel_preview.dart b/packages/stream_chat_flutter/lib/src/channel_preview.dart index 432f3354..4c0d2b42 100644 --- a/packages/stream_chat_flutter/lib/src/channel_preview.dart +++ b/packages/stream_chat_flutter/lib/src/channel_preview.dart @@ -198,7 +198,7 @@ class ChannelPreview extends StatelessWidget { size: 16, ), Text( - context.translations.channelIsMutedText, + ' ${context.translations.channelIsMutedText}', style: chatThemeData.channelPreviewTheme.subtitle, ), ], diff --git a/packages/stream_chat_flutter/lib/src/full_screen_media.dart b/packages/stream_chat_flutter/lib/src/full_screen_media.dart index 13ec3b3b..5e498a32 100644 --- a/packages/stream_chat_flutter/lib/src/full_screen_media.dart +++ b/packages/stream_chat_flutter/lib/src/full_screen_media.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:chewie/chewie.dart'; import 'package:flutter/material.dart'; -import 'package:jiffy/jiffy.dart'; import 'package:photo_view/photo_view.dart'; import 'package:stream_chat_flutter/src/gallery_footer.dart'; import 'package:stream_chat_flutter/src/gallery_header.dart'; @@ -183,7 +182,6 @@ class _FullScreenMediaState extends State children: [ GalleryHeader( userName: widget.userName, - // TODO: Fix this sentAt: context.translations.sentAtText( date: widget.message.createdAt, time: widget.message.createdAt, @@ -225,22 +223,6 @@ class _FullScreenMediaState extends State ), ); - String getDay(DateTime dateTime) { - final now = DateTime.now(); - - if (DateTime(dateTime.year, dateTime.month, dateTime.day) == - DateTime(now.year, now.month, now.day)) { - return 'today'; - } else if (DateTime(now.year, now.month, now.day) - .difference(dateTime) - .inHours < - 24) { - return 'yesterday'; - } else { - return 'on ${Jiffy(dateTime).MMMd}'; - } - } - @override void dispose() async { for (final package in videoPackages.values) { diff --git a/packages/stream_chat_flutter/lib/src/localization/translations.dart b/packages/stream_chat_flutter/lib/src/localization/translations.dart index 9b270bd5..4344dc8a 100644 --- a/packages/stream_chat_flutter/lib/src/localization/translations.dart +++ b/packages/stream_chat_flutter/lib/src/localization/translations.dart @@ -1,3 +1,4 @@ +import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart' show User; @@ -146,11 +147,6 @@ abstract class Translations { String get loadingChannelsError; - // title: 'Delete Conversation', -// okText: 'DELETE', -// question: -// 'Are you sure you want to delete this conversation?', - String get deleteConversationLabel; String get deleteConversationQuestion; @@ -274,7 +270,7 @@ class DefaultTranslations implements Translations { String resultCountText(int count) => '$count results'; @override - String get messageDeletedText => 'This message was deleted.'; + String get messageDeletedText => 'This message is deleted.'; @override String get messageDeletedLabel => 'Message deleted'; @@ -428,9 +424,22 @@ class DefaultTranslations implements Translations { @override String get photosLabel => 'Photos'; + String _getDay(DateTime dateTime) { + final now = Jiffy(DateTime.now()); + final date = Jiffy(dateTime); + + if (date.isSame(now, Units.DAY)) { + return 'today'; + } else if (now.diff(date, Units.HOUR) < 24) { + return 'yesterday'; + } else { + return 'on ${date.MMMd}'; + } + } + @override String sentAtText({required DateTime date, required DateTime time}) => - 'Sent $date at $time'; + 'Sent ${_getDay(date)} at ${Jiffy(time.toLocal()).format('HH:mm')}'; @override String get todayLabel => 'Today'; @@ -439,7 +448,7 @@ class DefaultTranslations implements Translations { String get yesterdayLabel => 'Yesterday'; @override - String get channelIsMutedText => ' Channel is muted'; + String get channelIsMutedText => 'Channel is muted'; @override String get noTitleText => 'No title'; diff --git a/packages/stream_chat_flutter/lib/src/user_item.dart b/packages/stream_chat_flutter/lib/src/user_item.dart index 99b35df1..a55693aa 100644 --- a/packages/stream_chat_flutter/lib/src/user_item.dart +++ b/packages/stream_chat_flutter/lib/src/user_item.dart @@ -92,8 +92,8 @@ class UserItem extends StatelessWidget { return Text( user.online == true ? context.translations.userOnlineText - : context.translations.userLastOnlineText + - Jiffy(user.lastActive).fromNow(), + : '${context.translations.userLastOnlineText} ' + '${Jiffy(user.lastActive).fromNow()}', style: chatTheme.textTheme.footnote.copyWith( color: chatTheme.colorTheme.textHighEmphasis.withOpacity(.5)), ); diff --git a/packages/stream_chat_flutter/lib/stream_chat_flutter.dart b/packages/stream_chat_flutter/lib/stream_chat_flutter.dart index 4b4fd9eb..eb690a9b 100644 --- a/packages/stream_chat_flutter/lib/stream_chat_flutter.dart +++ b/packages/stream_chat_flutter/lib/stream_chat_flutter.dart @@ -1,3 +1,4 @@ +export 'package:jiffy/jiffy.dart'; export 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; export 'src/attachment/attachment.dart'; @@ -16,6 +17,7 @@ export 'src/gallery_footer.dart'; export 'src/gallery_header.dart'; export 'src/info_tile.dart'; export 'src/localization/stream_chat_localizations.dart'; +export 'src/localization/translations.dart' show DefaultTranslations; export 'src/mention_tile.dart'; export 'src/message_action.dart'; export 'src/message_input.dart'; diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart index 4dba5948..82662134 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart @@ -1,11 +1,14 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:jiffy/jiffy.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart' show StreamChatLocalizations, User; part 'stream_chat_localizations_en.dart'; +part 'stream_chat_localizations_hi.dart'; + /// The set of supported languages, as language code strings. /// /// The [GlobalStreamChatLocalizations.delegate] can generate localizations for @@ -14,7 +17,7 @@ part 'stream_chat_localizations_en.dart'; /// See also: /// /// * [getStreamChatTranslation], whose documentation describes these values. -const kStreamChatSupportedLanguages = {'en'}; +const kStreamChatSupportedLanguages = {'en', 'hi'}; /// Creates a [GlobalStreamChatLocalizations] instance for the given `locale`. /// @@ -38,6 +41,8 @@ GlobalStreamChatLocalizations? getStreamChatTranslation(Locale locale) { switch (locale.languageCode) { case 'en': return const StreamChatLocalizationsEn(); + case 'hi': + return const StreamChatLocalizationsHi(); } } diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_en.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_en.dart index 91f41b64..88b88840 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_en.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_en.dart @@ -73,7 +73,7 @@ class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations { String resultCountText(int count) => '$count results'; @override - String get messageDeletedText => 'This message was deleted.'; + String get messageDeletedText => 'This message is deleted.'; @override String get messageDeletedLabel => 'Message deleted'; @@ -227,9 +227,22 @@ class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations { @override String get photosLabel => 'Photos'; + String _getDay(DateTime dateTime) { + final now = Jiffy(DateTime.now()); + final date = Jiffy(dateTime); + + if (date.isSame(now, Units.DAY)) { + return 'today'; + } else if (now.diff(date, Units.HOUR) < 24) { + return 'yesterday'; + } else { + return 'on ${date.MMMd}'; + } + } + @override String sentAtText({required DateTime date, required DateTime time}) => - 'Sent $date at $time'; + 'Sent ${_getDay(date)} at ${Jiffy(time.toLocal()).format('HH:mm')}'; @override String get todayLabel => 'Today'; @@ -238,7 +251,7 @@ class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations { String get yesterdayLabel => 'Yesterday'; @override - String get channelIsMutedText => ' Channel is muted'; + String get channelIsMutedText => 'Channel is muted'; @override String get noTitleText => 'No title'; diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_hi.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_hi.dart new file mode 100644 index 00000000..5666b77d --- /dev/null +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_hi.dart @@ -0,0 +1,353 @@ +part of 'stream_chat_localizations.dart'; + +/// The translations for English (`hi`). +class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations { + /// Create an instance of the translation bundle for Hindi. + const StreamChatLocalizationsHi({String localeName = 'hi'}) + : super(localeName: localeName); + + @override + String get launchUrlError => 'यूआरएल लॉन्च नहीं कर सकते'; + + @override + String get loadingUsersError => 'यूजर लोड करने में समस्या'; + + @override + String get noUsersLabel => 'वर्तमान में कोई यूजर नहीं हैं'; + + @override + String get retryLabel => 'पुन: प्रयास करे'; + + @override + String get userLastOnlineText => 'अंतिम ऑनलाइन'; + + @override + String get userOnlineText => 'ऑनलाइन'; + + @override + String userTypingText(Iterable users) { + if (users.isEmpty) return ''; + final first = users.first; + if (users.length == 1) { + return '${first.name} टाइप कर रहा है'; + } + return '${first.name} और ${users.length - 1} और टाइप कर रहे हैं'; + } + + @override + String get threadReplyLabel => 'थ्रेड जवाब'; + + @override + String get onlyVisibleToYouText => 'केवल आपको दिखाई दे रहा है'; + + @override + String threadReplyCountText(int count) => '$count थ्रेड जवाब'; + + @override + String attachmentsUploadProgressText({ + required int remaining, + required int total, + }) => + 'अपलोडिंग $remaining/$total ...'; + + @override + String pinnedByUserText({ + required User pinnedBy, + required User currentUser, + }) { + final pinnedByCurrentUser = currentUser.id == pinnedBy.id; + if (pinnedByCurrentUser) return 'आपके द्वारा पिन किया गया'; + return '${pinnedBy.name} द्वारा पिन किया गया'; + } + + @override + String get emptyMessagesText => 'वर्तमान में कोई संदेश नहीं है'; + + @override + String get genericErrorText => 'कुछ समस्या हो गई'; + + @override + String get loadingMessagesError => 'संदेश लोड करने में समस्या'; + + @override + String resultCountText(int count) => '$count परिणाम'; + + @override + String get messageDeletedText => 'यह संदेश हटा दिया गया है।'; + + @override + String get messageDeletedLabel => 'संदेश हटाये'; + + @override + String get messageReactionsText => 'संदेश प्रतिक्रियाएं'; + + @override + String get emptyChatMessagesText => 'यहां अभी तक कोई चैट नहीं...'; + + @override + String threadSeparatorText(int replyCount) { + if (replyCount == 1) return '1 जवाब'; + return '$replyCount जवाब'; + } + + @override + String get connectedLabel => 'कनेक्टेड'; + + @override + String get disconnectedLabel => 'डिस्कनेक्टेड'; + + @override + String get reconnectingLabel => 'पुनः कनेक्टिंग...'; + + @override + String get alsoSendAsDirectMessageLabel => 'सीधे संदेश के रूप में भी भेजें'; + + @override + String get addACommentOrSendLabel => 'एक टिप्पणी जोड़ें या भेजें'; + + @override + String get searchGifLabel => 'जीआईएफ खोजें'; + + @override + String get writeAMessageLabel => 'एक सन्देश लिखिए'; + + @override + String get instantCommandsLabel => 'तत्काल आदेश'; + + @override + String get fileTooLargeAfterCompressionError => + 'फ़ाइल अपलोड करने के लिए बहुत बड़ी है। ' + 'फ़ाइल आकार सीमा 20MB है। ' + 'हमने इसे कंप्रेस करने की कोशिश की, लेकिन यह काफी नहीं था।'; + + @override + String get fileTooLargeError => + 'फ़ाइल अपलोड करने के लिए बहुत बड़ी है। फ़ाइल आकार सीमा 20MB है।'; + + @override + String emojiMatchingQueryText(String query) => '"$query" से मिलते हुए इमोजी'; + + @override + String get addAFileLabel => 'एक फ़ाइल जोड़ें'; + + @override + String get photoFromCameraLabel => 'कैमरे से फोटो'; + + @override + String get uploadAFileLabel => 'एक फाइल अपलोड करें'; + + @override + String get uploadAPhotoLabel => 'एक फोटो अपलोड करो'; + + @override + String get uploadAVideoLabel => 'एक वीडियो अपलोड करें'; + + @override + String get videoFromCameraLabel => 'कैमरे से वीडियो'; + + @override + String get okLabel => 'ठीक'; + + @override + String get somethingWentWrongLabel => 'लोड करने में समस्या'; + + @override + String get addMoreFilesLabel => 'और फ़ाइलें जोड़ें'; + + @override + String get enablePhotoAndVideoAccessMessage => + 'कृपया अपने फ़ोटो और वीडियो तक पहुंच सक्षम करें' + '\nताकि आप उन्हें मित्रों के साथ साझा कर सकें।'; + + @override + String get allowGalleryAccessMessage => 'अपनी गैलरी तक पहुंच की अनुमति दें'; + + @override + String get flagMessageLabel => 'फ्लैग संदेश'; + + @override + String get flagMessageQuestion => 'क्या आप आगे की जांच के लिए इस संदेश की' + '\nएक प्रति मॉडरेटर को भेजना चाहते हैं?'; + + @override + String get flagLabel => 'फ्लैग'; + + @override + String get cancelLabel => 'रद्द करें'; + + @override + String get flagMessageSuccessfulLabel => 'संदेश फ्लैग हो गया'; + + @override + String get flagMessageSuccessfulText => + 'संदेश की रिपोर्ट एक मॉडरेटर को कर दी गई है।'; + + @override + String get deleteLabel => 'हटाएँ'; + + @override + String get deleteMessageLabel => 'संदेश हटाएं'; + + @override + String get deleteMessageQuestion => + 'क्या आप वाकई इस संदेश को स्थायी रूप से\nहटाना चाहते हैं?'; + + @override + String get operationCouldNotBeCompletedText => + 'कार्रवाई पूरी नहीं की जा सकी.'; + + @override + String get replyLabel => 'रिप्लाई'; + + @override + String togglePinUnpinText({required bool pinned}) { + if (pinned) return 'बातचीत से अनपिन करें'; + return 'बातचीत में पिन करें'; + } + + @override + String toggleDeleteRetryDeleteMessageText({required bool isDeleteFailed}) { + if (isDeleteFailed) return 'संदेश हटाने का पुनः प्रयास करें'; + return 'संदेश को हटाएं'; + } + + @override + String get copyMessageLabel => 'संदेश कॉपी करें'; + + @override + String get editMessageLabel => 'संदेश एडिट करें'; + + @override + String toggleResendOrResendEditedMessage({required bool isUpdateFailed}) { + if (isUpdateFailed) return 'एडिट संदेश फिर से भेजें'; + return 'पुन: भेजें'; + } + + @override + String get photosLabel => 'तस्वीरें'; + + String _getDay(DateTime dateTime) { + final now = Jiffy(DateTime.now()); + final date = Jiffy(dateTime); + + if (date.isSame(now, Units.DAY)) { + return 'आज'; + } else if (now.diff(date, Units.HOUR) < 24) { + return 'कल'; + } else { + return '${date.MMMd} को'; + } + } + + @override + String sentAtText({required DateTime date, required DateTime time}) => + '${_getDay(date)} ${Jiffy(time.toLocal()).format('HH:mm')} बजे भेजा गया'; + + @override + String get todayLabel => 'आज'; + + @override + String get yesterdayLabel => 'बिता हुआ कल'; + + @override + String get channelIsMutedText => 'चैनल मौन है'; + + @override + String get noTitleText => 'कोई शीर्षक नहीं'; + + @override + String get letsStartChattingLabel => 'चलो चैट करना शुरू करें!'; + + @override + String get sendingFirstMessageLabel => + 'किसी मित्र को अपना पहला संदेश भेजने के बारे में क्या विचार है?'; + + @override + String get startAChatLabel => 'चैट शुरू करें'; + + @override + String get loadingChannelsError => 'चैनल लोड करने में समस्या'; + + @override + String get deleteConversationLabel => 'वार्तालाप हटाए'; + + @override + String get deleteConversationQuestion => + 'क्या आप वाकई इस वार्तालाप को हटाना चाहते हैं?'; + + @override + String get streamChatLabel => 'स्ट्रीम चैट'; + + @override + String get searchingForNetworkLabel => 'नेटवर्क खोज रहे हैं'; + + @override + String get offlineLabel => 'ऑफलाइन...'; + + @override + String get tryAgainLabel => 'पुनः प्रयास करें'; + + @override + String membersCountText(int count) { + if (count == 1) return '1 सदस्य'; + return '$count सदस्य'; + } + + @override + String watchersCountText(int count) { + if (count == 1) return '1 ऑनलाइन'; + return '$count ऑनलाइन'; + } + + @override + String get viewInfoLabel => 'जानकारी देखें'; + + @override + String get leaveGroupLabel => 'समूह छोड़े'; + + @override + String get leaveLabel => 'छोड़े'; + + @override + String get leaveConversationLabel => 'वार्तालाप छोड़े'; + + @override + String get leaveConversationQuestion => + 'क्या आप वाकई इस बातचीत को छोड़ना चाहते हैं?'; + + @override + String get showInChatLabel => 'चैट में दिखाएं'; + + @override + String get saveImageLabel => 'चित्र को सेव करें'; + + @override + String get saveVideoLabel => 'वीडियो को सेव करे'; + + @override + String get uploadErrorLabel => 'अपलोड समस्या'; + + @override + String get giphyLabel => 'जिफ़ी'; + + @override + String get shuffleLabel => 'बदलें'; + + @override + String get sendLabel => 'भेजें'; + + @override + String get withText => 'विद'; + + @override + String get inText => 'इन'; + + @override + String get youText => 'आप'; + + @override + String get ofText => 'ऑफ़'; + + @override + String get fileText => 'फ़ाइल'; +}