diff --git a/packages/stream_chat_localizations/CHANGELOG.md b/packages/stream_chat_localizations/CHANGELOG.md index bc9efcfee9..337d62c6eb 100644 --- a/packages/stream_chat_localizations/CHANGELOG.md +++ b/packages/stream_chat_localizations/CHANGELOG.md @@ -1,3 +1,10 @@ +## Upcoming + +✅ Added + +- Added Azerbaijani (`az`) translations. +- Added Russian (`ru`) translations. + ## 10.0.1 🛑️ Breaking diff --git a/packages/stream_chat_localizations/README.md b/packages/stream_chat_localizations/README.md index 072b5cee71..ee8194b201 100644 --- a/packages/stream_chat_localizations/README.md +++ b/packages/stream_chat_localizations/README.md @@ -33,6 +33,8 @@ This package provides localized strings for all Stream Chat Flutter widgets. Dep - [Portuguese](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_pt.dart) - [German](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_de.dart) - [Norwegian](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_no.dart) +- [Azerbaijani](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_az.dart) +- [Russian](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ru.dart) More languages will be added in the future. Feel free to [contribute](https://github.com/GetStream/stream-chat-flutter/blob/master/CONTRIBUTING.md) to add more. @@ -79,6 +81,8 @@ class MyApp extends StatelessWidget { Locale('pt'), Locale('de'), Locale('no'), + Locale('az'), + Locale('ru'), ], // Add GlobalStreamChatLocalizations.delegates localizationsDelegates: GlobalStreamChatLocalizations.delegates, @@ -127,6 +131,8 @@ Example: pt de no + az + ru ``` 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 956b906cb4..6a1c64cf01 100644 --- a/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:stream_chat_flutter/stream_chat_flutter.dart'; +part 'stream_chat_localizations_az.dart'; part 'stream_chat_localizations_ca.dart'; part 'stream_chat_localizations_de.dart'; part 'stream_chat_localizations_en.dart'; @@ -14,6 +15,7 @@ part 'stream_chat_localizations_ja.dart'; part 'stream_chat_localizations_ko.dart'; part 'stream_chat_localizations_pt.dart'; part 'stream_chat_localizations_no.dart'; +part 'stream_chat_localizations_ru.dart'; /// The set of supported languages, as language code strings. /// @@ -24,6 +26,7 @@ part 'stream_chat_localizations_no.dart'; /// /// * [getStreamChatTranslation], whose documentation describes these values. const kStreamChatSupportedLanguages = { + 'az', 'en', 'hi', 'fr', @@ -35,6 +38,7 @@ const kStreamChatSupportedLanguages = { 'pt', 'de', 'no', + 'ru', }; /// Creates a [GlobalStreamChatLocalizations] instance for the given `locale`. @@ -57,6 +61,8 @@ GlobalStreamChatLocalizations? getStreamChatTranslation(Locale locale) { 'getStreamChatTranslation() called for unsupported locale "$locale"', ); switch (locale.languageCode) { + case 'az': + return const StreamChatLocalizationsAz(); case 'en': return const StreamChatLocalizationsEn(); case 'hi': @@ -79,6 +85,8 @@ GlobalStreamChatLocalizations? getStreamChatTranslation(Locale locale) { return const StreamChatLocalizationsDe(); case 'no': return const StreamChatLocalizationsNo(); + case 'ru': + return const StreamChatLocalizationsRu(); default: return null; } diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_az.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_az.dart new file mode 100644 index 0000000000..039f2e6f3c --- /dev/null +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_az.dart @@ -0,0 +1,825 @@ +// ignore_for_file: lines_longer_than_80_chars + +part of 'stream_chat_localizations.dart'; + +/// The translations for Azerbaijani (`az`). +class StreamChatLocalizationsAz extends GlobalStreamChatLocalizations { + /// Create an instance of the translation bundle for Azerbaijani. + const StreamChatLocalizationsAz({super.localeName = 'az'}); + + @override + String get launchUrlError => 'URL-ni açmaq mümkün olmadı'; + + @override + String get loadingUsersError => 'İstifadəçilər yüklənərkən xəta baş verdi'; + + @override + String get noUsersLabel => 'Hal-hazırda istifadəçi yoxdur'; + + @override + String get noPhotoOrVideoLabel => 'Foto və ya video yoxdur'; + + @override + String get retryLabel => 'Yenidən cəhd et'; + + @override + String get userLastOnlineText => 'Son onlayn'; + + @override + String get userOnlineText => 'Onlayn'; + + @override + String userTypingText(Iterable users) { + if (users.isEmpty) return ''; + final first = users.first; + if (users.length == 1) { + return '${first.name} yazır'; + } + return '${first.name} və daha ${users.length - 1} nəfər yazır'; + } + + @override + String get threadReplyLabel => 'Mövzuya cavab'; + + @override + String get threadLabel => 'Mövzu'; + + @override + String get onlyVisibleToYouText => 'Yalnız sizə görünür'; + + @override + String threadReplyCountText(int count) => count == 1 ? '1 cavab' : '$count cavab'; + + @override + String attachmentsUploadProgressText({ + required int completed, + required int total, + }) => + '$total-dən $completed yükləndi ...'; + + @override + String pinnedByUserText({ + required User pinnedBy, + required User currentUser, + }) { + final pinnedByCurrentUser = currentUser.id == pinnedBy.id; + if (pinnedByCurrentUser) return 'Siz sabitlədiniz'; + return '${pinnedBy.name} sabitlədi'; + } + + @override + String get sendMessagePermissionError => 'Mesaj göndərmək üçün icazəniz yoxdur'; + + @override + String get emptyMessagesText => 'Hələ mesaj yoxdur'; + + @override + String get genericErrorText => 'Nə isə səhv getdi'; + + @override + String get loadingMessagesError => 'Mesajlar yüklənərkən xəta baş verdi'; + + @override + String resultCountText(int count) => '$count nəticə'; + + @override + String get messageDeletedText => 'Bu mesaj silindi.'; + + @override + String get messageDeletedLabel => 'Mesaj silindi'; + + @override + String get systemMessageLabel => 'Sistem mesajı'; + + @override + String get editedMessageLabel => 'Redaktə edildi'; + + @override + String get messageReactionsLabel => 'Mesaj reaksiyaları'; + + @override + String get emptyChatMessagesText => 'Hələ söhbət yoxdur...'; + + @override + String threadSeparatorText(int replyCount) { + if (replyCount == 1) return '1 cavab'; + return '$replyCount cavab'; + } + + @override + String get connectedLabel => 'Qoşuldu'; + + @override + String get disconnectedLabel => 'Bağlantı kəsildi'; + + @override + String get reconnectingLabel => 'Yenidən qoşulur...'; + + @override + String get alsoSendAsDirectMessageLabel => 'Həmçinin Kanalda göndər'; + + @override + String get addACommentOrSendLabel => 'Şərh əlavə et və ya göndər'; + + @override + String get searchGifLabel => 'GIF axtar'; + + @override + String get writeAMessageLabel => 'Mesaj göndər'; + + @override + String get instantCommandsLabel => 'Ani əmrlər'; + + @override + String fileTooLargeAfterCompressionError(double limitInMB) => 'Fayl yükləmək üçün çox böyükdür. ' + 'Fayl ölçüsü limiti $limitInMB MB-dır. ' + 'Onu sıxmağa cəhd etdik, lakin bu kifayət etmədi.'; + + @override + String fileTooLargeError(double limitInMB) => + 'Fayl yükləmək üçün çox böyükdür. Fayl ölçüsü limiti $limitInMB MB-dır.'; + + @override + String fileTypeNotSupportedError(String? extension) { + if (extension != null) { + return "'.$extension' faylları yükləmə üçün dəstəklənmir."; + } + return 'Bu fayl növü yükləmə üçün dəstəklənmir.'; + } + + @override + String get couldNotReadBytesFromFileError => 'Fayldan baytları oxumaq mümkün olmadı.'; + + @override + String get addAFileLabel => 'Fayl əlavə et'; + + @override + String get photoFromCameraLabel => 'Kameradan foto'; + + @override + String get uploadAFileLabel => 'Fayl yüklə'; + + @override + String get uploadAPhotoLabel => 'Foto yüklə'; + + @override + String get uploadAVideoLabel => 'Video yüklə'; + + @override + String get videoFromCameraLabel => 'Kameradan video'; + + @override + String get okLabel => 'OK'; + + @override + String get somethingWentWrongError => 'Nə isə səhv getdi'; + + @override + String get addMoreFilesLabel => 'Daha çox əlavə et'; + + @override + String get enablePhotoAndVideoAccessMessage => + 'Zəhmət olmasa, foto və videolarınıza giriş icazəsi verin ki, onları dostlarınızla paylaşa biləsiniz.'; + + @override + String get allowGalleryAccessMessage => 'Qalereyaya giriş icazəsi ver'; + + @override + String get flagMessageLabel => 'Mesajı şikayət et'; + + @override + String get flagMessageQuestion => 'Bu mesajın surətini əlavə araşdırma üçün bir moderatora göndərmək istəyirsiniz?'; + + @override + String get flagLabel => 'Şikayət et'; + + @override + String get cancelLabel => 'Ləğv et'; + + @override + String get flagMessageSuccessfulLabel => 'Mesaj şikayət edildi'; + + @override + String get flagMessageSuccessfulText => 'Mesaj moderatora bildirildi.'; + + @override + String get deleteLabel => 'Sil'; + + @override + String get deleteMessageLabel => 'Mesajı sil'; + + @override + String get deleteMessageQuestion => 'Bu mesajı həmişəlik silmək istədiyinizə əminsiniz?'; + + @override + String get operationCouldNotBeCompletedText => 'Əməliyyat tamamlana bilmədi.'; + + @override + String get replyLabel => 'Cavab ver'; + + @override + String togglePinUnpinText({required bool pinned}) { + if (pinned) return 'Söhbətdə sabitləməni ləğv et'; + return 'Söhbətdə sabitlə'; + } + + @override + String toggleDeleteRetryDeleteMessageText({required bool isDeleteFailed}) { + if (isDeleteFailed) return 'Mesajı silməyi yenidən cəhd et'; + return 'Mesajı sil'; + } + + @override + String get copyMessageLabel => 'Mesajı kopyala'; + + @override + String get editMessageLabel => 'Mesajı redaktə et'; + + @override + String toggleResendOrResendEditedMessage({required bool isUpdateFailed}) { + if (isUpdateFailed) return 'Redaktə edilmiş mesajı yenidən göndər'; + return 'Yenidən göndər'; + } + + @override + String get photosLabel => 'Fotolar'; + + @override + String get photosAndVideosLabel => 'Foto və Videolar'; + + String _getDay(DateTime dateTime) { + final now = DateTime.now(); + final today = DateTime(now.year, now.month, now.day); + final yesterday = DateTime(now.year, now.month, now.day - 1); + + final date = DateTime(dateTime.year, dateTime.month, dateTime.day); + + if (date == today) { + return 'bu gün'; + } else if (date == yesterday) { + return 'dünən'; + } else { + return '${Jiffy.parseFromDateTime(date).MMMd} tarixində'; + } + } + + @override + String sentAtText({required DateTime date, required DateTime time}) { + final atTime = Jiffy.parseFromDateTime(time.toLocal()); + return '${_getDay(date)} saat ${atTime.jm} göndərildi'; + } + + @override + String get todayLabel => 'Bu gün'; + + @override + String get yesterdayLabel => 'Dünən'; + + @override + String get channelIsMutedText => 'Kanal səssizdir'; + + @override + String get noTitleText => 'Başlıq yoxdur'; + + @override + String get letsStartChattingLabel => 'Gəlin söhbətə başlayaq!'; + + @override + String get sendingFirstMessageLabel => 'Dostunuza ilk mesajınızı göndərməyə nə deyirsiniz?'; + + @override + String get startAChatLabel => 'Söhbətə başla'; + + @override + String get loadingChannelsError => 'Kanallar yüklənərkən xəta baş verdi'; + + @override + String get deleteConversationLabel => 'Söhbəti sil'; + + @override + String get deleteConversationQuestion => 'Bu söhbəti silmək istədiyinizə əminsiniz?'; + + @override + String get streamChatLabel => 'Söhbətlər'; + + @override + String get searchingForNetworkText => 'Şəbəkə axtarılır'; + + @override + String get offlineLabel => 'Oflayn...'; + + @override + String get tryAgainLabel => 'Yenidən cəhd et'; + + @override + String membersCountText(int count) { + if (count == 1) return '1 üzv'; + return '$count üzv'; + } + + @override + String watchersCountText(int count) { + if (count == 1) return '1 onlayn'; + return '$count onlayn'; + } + + @override + String membersCountWithOnlineText({ + required int memberCount, + required int onlineCount, + }) { + final members = membersCountText(memberCount); + if (onlineCount <= 0) return members; + return '$members, ${watchersCountText(onlineCount)}'; + } + + @override + String get viewInfoLabel => 'Məlumata bax'; + + @override + String get leaveGroupLabel => 'Qrupdan çıx'; + + @override + String get leaveLabel => 'ÇIX'; + + @override + String get leaveConversationLabel => 'Söhbətdən çıx'; + + @override + String get leaveConversationQuestion => 'Bu söhbətdən çıxmaq istədiyinizə əminsiniz?'; + + @override + String get showInChatLabel => 'Söhbətdə göstər'; + + @override + String get saveImageLabel => 'Şəkli yadda saxla'; + + @override + String get saveVideoLabel => 'Videonu yadda saxla'; + + @override + String get uploadErrorLabel => 'YÜKLƏMƏ XƏTASI'; + + @override + String get giphyLabel => 'Giphy'; + + @override + String get shuffleLabel => 'Qarışdır'; + + @override + String get sendLabel => 'Göndər'; + + @override + String get withText => 'ilə'; + + @override + String get inText => 'içində'; + + @override + String get youText => 'Siz'; + + @override + String galleryPaginationText({ + required int currentPage, + required int totalPages, + }) => + '${currentPage + 1} / $totalPages'; + + @override + String get fileText => 'Fayl'; + + @override + String get replyToMessageLabel => 'Mesaja cavab ver'; + + @override + String attachmentLimitExceedError(int limit) => 'Qoşma limiti aşıldı, limit: $limit'; + + @override + String slowModeOnLabel(int cooldownTimeOut) => 'Yavaş rejim, $cooldownTimeOut s gözləyin…'; + + @override + String get commandUsernameLabel => '@istifadəçi_adı'; + + @override + String get downloadLabel => 'Endir'; + + @override + String toggleMuteUnmuteUserText({required bool isMuted}) { + if (isMuted) { + return 'İstifadəçinin səsini aç'; + } else { + return 'İstifadəçini səssiz et'; + } + } + + @override + String toggleBlockUnblockUserText({required bool isBlocked}) { + if (isBlocked) return 'İstifadəçinin blokunu aç'; + return 'İstifadəçini blokla'; + } + + @override + String toggleMuteUnmuteGroupQuestion({required bool isMuted}) { + if (isMuted) { + return 'Bu qrupun səsini açmaq istədiyinizə əminsiniz?'; + } else { + return 'Bu qrupu səssiz etmək istədiyinizə əminsiniz?'; + } + } + + @override + String toggleMuteUnmuteUserQuestion({required bool isMuted}) { + if (isMuted) { + return 'Bu istifadəçinin səsini açmaq istədiyinizə əminsiniz?'; + } else { + return 'Bu istifadəçini səssiz etmək istədiyinizə əminsiniz?'; + } + } + + @override + String toggleMuteUnmuteAction({required bool isMuted}) { + if (isMuted) { + return 'SƏSİNİ AÇ'; + } else { + return 'SƏSSİZ ET'; + } + } + + @override + String toggleMuteUnmuteGroupText({required bool isMuted}) { + if (isMuted) { + return 'Qrupun səsini aç'; + } else { + return 'Qrupu səssiz et'; + } + } + + @override + String get linkDisabledDetails => 'Bu söhbətdə link göndərmək qadağandır.'; + + @override + String get linkDisabledError => 'Linklər deaktivdir'; + + @override + String get viewLibrary => 'Kitabxanaya bax'; + + @override + String unreadMessagesSeparatorText() => 'Yeni mesajlar'; + + @override + String get enableFileAccessMessage => + 'Zəhmət olmasa, fayllara giriş icazəsi verin ki, onları dostlarınızla paylaşa biləsiniz.'; + + @override + String get allowFileAccessMessage => 'Fayllara giriş icazəsi ver'; + + @override + String get markAsUnreadLabel => 'Oxunmamış işarələ'; + + @override + String unreadCountIndicatorLabel({required int unreadCount}) { + return '$unreadCount oxunmamış'; + } + + @override + String get markUnreadError => 'Mesaj oxunmamış kimi işarələnərkən xəta baş verdi. Ən son 100 kanal ' + 'mesajından köhnə mesajları oxunmamış kimi işarələmək mümkün deyil.'; + + @override + String createPollLabel({bool isNew = false}) { + if (isNew) return 'Yeni sorğu yarat'; + return 'Sorğu yarat'; + } + + @override + String questionLabel({bool isPlural = false}) { + if (isPlural) return 'Suallar'; + return 'Sual'; + } + + @override + String get askAQuestionLabel => 'Sual ver'; + + @override + String? pollQuestionValidationError(int length, Range range) { + final (:min, :max) = range; + + if (min != null && length < min) { + return 'Sual ən azı $min simvol olmalıdır'; + } + + if (max != null && length > max) { + return 'Sual ən çoxu $max simvol ola bilər'; + } + + return null; + } + + @override + String optionLabel({bool isPlural = false}) { + if (isPlural) return 'Variantlar'; + return 'Variant'; + } + + @override + String get pollOptionEmptyError => 'Variant boş ola bilməz'; + + @override + String get pollOptionDuplicateError => 'Bu variant artıq mövcuddur'; + + @override + String get addAnOptionLabel => 'Variant əlavə et'; + + @override + String get multipleAnswersLabel => 'Çoxlu cavab'; + + @override + String get maximumVotesPerPersonLabel => 'Hər şəxs üçün maksimum səs'; + + @override + String? maxVotesPerPersonValidationError(int votes, Range range) { + final (:min, :max) = range; + + if (min != null && votes < min) { + return 'Səs sayı ən azı $min olmalıdır'; + } + + if (max != null && votes > max) { + return 'Səs sayı ən çoxu $max ola bilər'; + } + + return null; + } + + @override + String get anonymousPollLabel => 'Anonim sorğu'; + + @override + String get pollOptionsLabel => 'Sorğu variantları'; + + @override + String get suggestAnOptionLabel => 'Variant təklif et'; + + @override + String get enterANewOptionLabel => 'Yeni variant daxil et'; + + @override + String get addACommentLabel => 'Şərh əlavə et'; + + @override + String get pollCommentsLabel => 'Sorğu şərhləri'; + + @override + String get updateYourCommentLabel => 'Şərhinizi yeniləyin'; + + @override + String get enterYourCommentLabel => 'Şərhinizi daxil edin'; + + @override + String get endVoteConfirmationTitle => 'Bu sorğunu bitirək?'; + + @override + String get endVoteConfirmationMessage => + 'Bu sorğunu indi bitirmək istəyirsiniz? Bundan sonra heç kim bu sorğuda səs verə bilməyəcək.'; + + @override + String get deletePollOptionLabel => 'Variantı sil'; + + @override + String get deletePollOptionQuestion => 'Bu variantı silmək istədiyinizə əminsiniz?'; + + @override + String get createLabel => 'Yarat'; + + @override + String get endLabel => 'Bitir'; + + @override + String pollVotingModeLabel(PollVotingMode votingMode) { + return votingMode.when( + disabled: () => 'Səsvermə bitdi', + unique: () => 'Birini seç', + limited: (count) => 'Maksimum $count seç', + all: () => 'Bir və ya bir neçəsini seç', + ); + } + + @override + String seeAllOptionsLabel({int? count}) { + if (count == null) return 'Bütün variantlara bax'; + return 'Bütün $count variantı gör'; + } + + @override + String get viewCommentsLabel => 'Şərhlərə bax'; + + @override + String get viewResultsLabel => 'Nəticələrə bax'; + + @override + String get endVoteLabel => 'Sorğunu bitir'; + + @override + String get pollResultsLabel => 'Sorğu nəticələri'; + + @override + String get pollVotesLabel => 'Səslər'; + + @override + String showAllVotesLabel({int? count}) { + if (count == null) return 'Bütün səsləri göstər'; + return 'Bütün $count səsi göstər'; + } + + @override + String get viewAllLabel => 'Hamısına bax'; + + @override + String voteCountLabel({int? count}) => switch (count) { + null || < 1 => '0 səs', + 1 => '1 səs', + _ => '$count səs', + }; + + @override + String totalVoteCountLabel({int? count}) => switch (count) { + null || < 1 => 'cəmi 0 səs', + 1 => 'cəmi 1 səs', + _ => 'cəmi $count səs', + }; + + @override + String get noPollVotesLabel => 'Hal-hazırda səs yoxdur'; + + @override + String get loadingPollVotesError => 'Səslər yüklənərkən xəta baş verdi'; + + @override + String get repliedToLabel => 'cavab verdi:'; + + @override + String newThreadsLabel({required int count}) { + if (count == 1) return '1 yeni mövzu'; + return '$count yeni mövzu'; + } + + @override + String get loadingLabel => 'Yüklənir...'; + + @override + String get slideToCancelLabel => 'Ləğv etmək üçün sürüşdür'; + + @override + String get holdToRecordLabel => 'Yazmaq üçün basılı saxla. Saxlamaq üçün burax.'; + + @override + String get sendAnywayLabel => 'Yenə də göndər'; + + @override + String get moderatedMessageBlockedText => 'Mesaj moderasiya qaydalarına görə bloklandı'; + + @override + String get moderationReviewModalTitle => 'Əminsiniz?'; + + @override + String get moderationReviewModalDescription => + '''Şərhinizin başqalarında necə təəssürat yarada biləcəyini düşünün və icma qaydalarımıza riayət etdiyinizə əmin olun.'''; + + @override + String get emptyMessagePreviewText => ''; + + @override + String get voiceRecordingText => 'Səs yazısı'; + + @override + String get audioAttachmentText => 'Audio'; + + @override + String get imageAttachmentText => 'Şəkil'; + + @override + String get videoAttachmentText => 'Video'; + + @override + String get fileAttachmentText => 'Fayl'; + + @override + String get linkAttachmentText => 'Link'; + + @override + String filesAttachmentCountText(int count) => count == 1 ? 'Fayl' : '$count fayl'; + + @override + String photosAttachmentCountText(int count) => count == 1 ? 'Foto' : '$count foto'; + + @override + String videosAttachmentCountText(int count) => count == 1 ? 'Video' : '$count video'; + + @override + String get pollYouVotedText => 'Siz səs verdiniz'; + + @override + String pollSomeoneVotedText(String username) => '$username səs verdi'; + + @override + String get pollYouCreatedText => 'Siz yaratdınız'; + + @override + String pollSomeoneCreatedText(String username) => '$username yaratdı'; + + @override + String get draftLabel => 'Qaralama'; + + @override + String locationLabel({bool isLive = false}) { + if (isLive) return 'Canlı məkan'; + return 'Məkan'; + } + + @override + String get noConversationsYetText => 'Hələ söhbət yoxdur'; + + @override + String get replyToStartThreadText => 'Mövzu başlatmaq üçün mesaja cavab verin'; + + @override + String get sendMessageToStartConversationText => 'Söhbətə başlamaq üçün mesaj göndərin'; + + @override + String get savedForLaterLabel => 'Sonraya saxlanıldı'; + + @override + String get repliedToThreadAnnotationLabel => 'Mövzuya cavab verdi'; + + @override + String get alsoSentInChannelAnnotationLabel => 'Həmçinin kanalda göndərildi'; + + @override + String get viewLabel => 'Bax'; + + @override + String get reminderSetLabel => 'Xatırlatma quruldu'; + + @override + String reminderAtText(String time) => 'Bu gün saat $time'; + + @override + String get createPollPromptLabel => 'Sorğu yaradın və hamı səs versin!'; + + @override + String get takePhotoAndShareLabel => 'Foto çək və paylaş'; + + @override + String get takeVideoAndShareLabel => 'Video çək və paylaş'; + + @override + String get openCameraLabel => 'Kameranı aç'; + + @override + String get selectFilesToShareLabel => 'Paylaşmaq üçün fayllar seçin'; + + @override + String get openFilesLabel => 'Faylları aç'; + + @override + String get unsupportedAttachmentLabel => 'Dəstəklənməyən qoşma'; + + @override + String get confirmLabel => 'TƏSDİQLƏ'; + + @override + String get emptyReactionsText => 'Hələ reaksiya yoxdur'; + + @override + String get loadingReactionsError => 'Reaksiyalar yüklənərkən xəta baş verdi'; + + @override + String get tapToRemoveReactionLabel => 'Silmək üçün toxun'; + + @override + String reactionsCountText(int count) => count == 1 ? '1 reaksiya' : '$count reaksiya'; + + @override + String get justNowLabel => 'İndicə'; + + @override + String replyToUserLabel(String userName) => '$userName istifadəçisinə cavab ver'; + + @override + String get multipleAnswersDescription => 'Birdən çox variant seçin'; + + @override + String maximumVotesPerPersonDescription([Range? range]) { + final (:min, :max) = range ?? (min: 2, max: 10); + return '$min–$max arası variant seçin'; + } + + @override + String get anonymousPollDescription => 'Kimin səs verdiyini gizlət'; + + @override + String get suggestAnOptionDescription => 'Başqalarının variant əlavə etməsinə icazə ver'; + + @override + String get addACommentDescription => 'Başqalarının şərh əlavə etməsinə icazə ver'; +} diff --git a/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ru.dart b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ru.dart new file mode 100644 index 0000000000..7a9a9855b9 --- /dev/null +++ b/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ru.dart @@ -0,0 +1,833 @@ +// ignore_for_file: lines_longer_than_80_chars + +part of 'stream_chat_localizations.dart'; + +/// The translations for Russian (`ru`). +class StreamChatLocalizationsRu extends GlobalStreamChatLocalizations { + /// Create an instance of the translation bundle for Russian. + const StreamChatLocalizationsRu({super.localeName = 'ru'}); + + /// Selects the correct Russian plural form for [count]. + /// + /// Russian has three plural forms: [one] (e.g. 1, 21, 31), [few] + /// (e.g. 2, 3, 4, 22) and [many] (e.g. 5, 11, 12, 25). + String _plural( + int count, { + required String one, + required String few, + required String many, + }) { + final mod10 = count % 10; + final mod100 = count % 100; + if (mod10 == 1 && mod100 != 11) return one; + if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return few; + return many; + } + + @override + String get launchUrlError => 'Не удалось открыть ссылку'; + + @override + String get loadingUsersError => 'Ошибка загрузки пользователей'; + + @override + String get noUsersLabel => 'Сейчас нет пользователей'; + + @override + String get noPhotoOrVideoLabel => 'Нет фото или видео'; + + @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 threadLabel => 'Тред'; + + @override + String get onlyVisibleToYouText => 'Видно только вам'; + + @override + String threadReplyCountText(int count) => '$count ${_plural(count, one: 'ответ', few: 'ответа', many: 'ответов')}'; + + @override + String attachmentsUploadProgressText({ + required int completed, + required int total, + }) => 'Загружено $completed из $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 sendMessagePermissionError => 'У вас нет разрешения отправлять сообщения'; + + @override + String get emptyMessagesText => 'Сообщений пока нет'; + + @override + String get genericErrorText => 'Что-то пошло не так'; + + @override + String get loadingMessagesError => 'Ошибка загрузки сообщений'; + + @override + String resultCountText(int count) => + '$count ${_plural(count, one: 'результат', few: 'результата', many: 'результатов')}'; + + @override + String get messageDeletedText => 'Это сообщение удалено.'; + + @override + String get messageDeletedLabel => 'Сообщение удалено'; + + @override + String get systemMessageLabel => 'Системное сообщение'; + + @override + String get editedMessageLabel => 'Изменено'; + + @override + String get messageReactionsLabel => 'Реакции на сообщение'; + + @override + String get emptyChatMessagesText => 'Здесь пока нет чатов...'; + + @override + String threadSeparatorText(int replyCount) => + '$replyCount ${_plural(replyCount, one: 'ответ', few: 'ответа', many: 'ответов')}'; + + @override + String get connectedLabel => 'Подключено'; + + @override + String get disconnectedLabel => 'Отключено'; + + @override + String get reconnectingLabel => 'Переподключение...'; + + @override + String get alsoSendAsDirectMessageLabel => 'Также отправить в канал'; + + @override + String get addACommentOrSendLabel => 'Добавьте комментарий или отправьте'; + + @override + String get searchGifLabel => 'Поиск GIF'; + + @override + String get writeAMessageLabel => 'Отправить сообщение'; + + @override + String get instantCommandsLabel => 'Быстрые команды'; + + @override + String fileTooLargeAfterCompressionError(double limitInMB) => + 'Файл слишком большой для загрузки. ' + 'Ограничение размера файла — $limitInMB МБ. ' + 'Мы попытались сжать его, но этого оказалось недостаточно.'; + + @override + String fileTooLargeError(double limitInMB) => + 'Файл слишком большой для загрузки. Ограничение размера файла — $limitInMB МБ.'; + + @override + String fileTypeNotSupportedError(String? extension) { + if (extension != null) { + return 'Файлы «.$extension» не поддерживаются для загрузки.'; + } + return 'Этот тип файла не поддерживается для загрузки.'; + } + + @override + String get couldNotReadBytesFromFileError => 'Не удалось прочитать байты из файла.'; + + @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 somethingWentWrongError => 'Что-то пошло не так'; + + @override + String get addMoreFilesLabel => 'Добавить ещё'; + + @override + String get enablePhotoAndVideoAccessMessage => + 'Пожалуйста, разрешите доступ к фото и видео, чтобы делиться ими с друзьями.'; + + @override + String get allowGalleryAccessMessage => 'Разрешить доступ к галерее'; + + @override + String get flagMessageLabel => 'Пожаловаться на сообщение'; + + @override + String get flagMessageQuestion => 'Хотите отправить копию этого сообщения модератору для дальнейшего рассмотрения?'; + + @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 => 'Вы уверены, что хотите безвозвратно удалить это сообщение?'; + + @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 => 'Фото'; + + @override + String get photosAndVideosLabel => 'Фото и видео'; + + String _getDay(DateTime dateTime) { + final now = DateTime.now(); + final today = DateTime(now.year, now.month, now.day); + final yesterday = DateTime(now.year, now.month, now.day - 1); + + final date = DateTime(dateTime.year, dateTime.month, dateTime.day); + + if (date == today) { + return 'сегодня'; + } else if (date == yesterday) { + return 'вчера'; + } else { + return Jiffy.parseFromDateTime(date).MMMd; + } + } + + @override + String sentAtText({required DateTime date, required DateTime time}) { + final atTime = Jiffy.parseFromDateTime(time.toLocal()); + return 'Отправлено ${_getDay(date)} в ${atTime.jm}'; + } + + @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 searchingForNetworkText => 'Поиск сети'; + + @override + String get offlineLabel => 'Не в сети...'; + + @override + String get tryAgainLabel => 'Повторить'; + + @override + String membersCountText(int count) => + '$count ${_plural(count, one: 'участник', few: 'участника', many: 'участников')}'; + + @override + String watchersCountText(int count) => '$count в сети'; + + @override + String membersCountWithOnlineText({ + required int memberCount, + required int onlineCount, + }) { + final members = membersCountText(memberCount); + if (onlineCount <= 0) return members; + return '$members, ${watchersCountText(onlineCount)}'; + } + + @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 => 'Giphy'; + + @override + String get shuffleLabel => 'Перемешать'; + + @override + String get sendLabel => 'Отправить'; + + @override + String get withText => 'с'; + + @override + String get inText => 'в'; + + @override + String get youText => 'Вы'; + + @override + String galleryPaginationText({ + required int currentPage, + required int totalPages, + }) => '${currentPage + 1} из $totalPages'; + + @override + String get fileText => 'Файл'; + + @override + String get replyToMessageLabel => 'Ответить на сообщение'; + + @override + String attachmentLimitExceedError(int limit) => 'Превышен лимит вложений, лимит: $limit'; + + @override + String slowModeOnLabel(int cooldownTimeOut) => 'Медленный режим, подождите $cooldownTimeOut с…'; + + @override + String get commandUsernameLabel => '@имя_пользователя'; + + @override + String get downloadLabel => 'Скачать'; + + @override + String toggleMuteUnmuteUserText({required bool isMuted}) { + if (isMuted) { + return 'Включить звук пользователя'; + } else { + return 'Отключить звук пользователя'; + } + } + + @override + String toggleBlockUnblockUserText({required bool isBlocked}) { + if (isBlocked) return 'Разблокировать пользователя'; + return 'Заблокировать пользователя'; + } + + @override + String toggleMuteUnmuteGroupQuestion({required bool isMuted}) { + if (isMuted) { + return 'Вы уверены, что хотите включить звук в этой группе?'; + } else { + return 'Вы уверены, что хотите отключить звук в этой группе?'; + } + } + + @override + String toggleMuteUnmuteUserQuestion({required bool isMuted}) { + if (isMuted) { + return 'Вы уверены, что хотите включить звук этого пользователя?'; + } else { + return 'Вы уверены, что хотите отключить звук этого пользователя?'; + } + } + + @override + String toggleMuteUnmuteAction({required bool isMuted}) { + if (isMuted) { + return 'ВКЛ. ЗВУК'; + } else { + return 'ВЫКЛ. ЗВУК'; + } + } + + @override + String toggleMuteUnmuteGroupText({required bool isMuted}) { + if (isMuted) { + return 'Включить звук группы'; + } else { + return 'Отключить звук группы'; + } + } + + @override + String get linkDisabledDetails => 'Отправка ссылок запрещена в этой беседе.'; + + @override + String get linkDisabledError => 'Ссылки отключены'; + + @override + String get viewLibrary => 'Открыть библиотеку'; + + @override + String unreadMessagesSeparatorText() => 'Новые сообщения'; + + @override + String get enableFileAccessMessage => 'Пожалуйста, разрешите доступ к файлам, чтобы делиться ими с друзьями.'; + + @override + String get allowFileAccessMessage => 'Разрешить доступ к файлам'; + + @override + String get markAsUnreadLabel => 'Отметить непрочитанным'; + + @override + String unreadCountIndicatorLabel({required int unreadCount}) => + '$unreadCount ${_plural(unreadCount, one: 'непрочитанное', few: 'непрочитанных', many: 'непрочитанных')}'; + + @override + String get markUnreadError => + 'Ошибка при отметке сообщения непрочитанным. Нельзя отметить ' + 'непрочитанными сообщения старше последних 100 сообщений канала.'; + + @override + String createPollLabel({bool isNew = false}) { + if (isNew) return 'Создать новый опрос'; + return 'Создать опрос'; + } + + @override + String questionLabel({bool isPlural = false}) { + if (isPlural) return 'Вопросы'; + return 'Вопрос'; + } + + @override + String get askAQuestionLabel => 'Задайте вопрос'; + + @override + String? pollQuestionValidationError(int length, Range range) { + final (:min, :max) = range; + + if (min != null && length < min) { + return 'Вопрос должен содержать не менее $min символов'; + } + + if (max != null && length > max) { + return 'Вопрос должен содержать не более $max символов'; + } + + return null; + } + + @override + String optionLabel({bool isPlural = false}) { + if (isPlural) return 'Варианты'; + return 'Вариант'; + } + + @override + String get pollOptionEmptyError => 'Вариант не может быть пустым'; + + @override + String get pollOptionDuplicateError => 'Такой вариант уже есть'; + + @override + String get addAnOptionLabel => 'Добавить вариант'; + + @override + String get multipleAnswersLabel => 'Несколько ответов'; + + @override + String get maximumVotesPerPersonLabel => 'Максимум голосов на человека'; + + @override + String? maxVotesPerPersonValidationError(int votes, Range range) { + final (:min, :max) = range; + + if (min != null && votes < min) { + return 'Количество голосов должно быть не менее $min'; + } + + if (max != null && votes > max) { + return 'Количество голосов должно быть не более $max'; + } + + return null; + } + + @override + String get anonymousPollLabel => 'Анонимный опрос'; + + @override + String get pollOptionsLabel => 'Варианты опроса'; + + @override + String get suggestAnOptionLabel => 'Предложить вариант'; + + @override + String get enterANewOptionLabel => 'Введите новый вариант'; + + @override + String get addACommentLabel => 'Добавить комментарий'; + + @override + String get pollCommentsLabel => 'Комментарии к опросу'; + + @override + String get updateYourCommentLabel => 'Обновите ваш комментарий'; + + @override + String get enterYourCommentLabel => 'Введите ваш комментарий'; + + @override + String get endVoteConfirmationTitle => 'Завершить опрос?'; + + @override + String get endVoteConfirmationMessage => + 'Хотите завершить этот опрос сейчас? После этого никто не сможет в нём голосовать.'; + + @override + String get deletePollOptionLabel => 'Удалить вариант'; + + @override + String get deletePollOptionQuestion => 'Вы уверены, что хотите удалить этот вариант?'; + + @override + String get createLabel => 'Создать'; + + @override + String get endLabel => 'Завершить'; + + @override + String pollVotingModeLabel(PollVotingMode votingMode) { + return votingMode.when( + disabled: () => 'Голосование завершено', + unique: () => 'Выберите один', + limited: (count) => 'Выберите до $count', + all: () => 'Выберите один или несколько', + ); + } + + @override + String seeAllOptionsLabel({int? count}) { + if (count == null) return 'Посмотреть все варианты'; + return 'Посмотреть все $count ${_plural(count, one: 'вариант', few: 'варианта', many: 'вариантов')}'; + } + + @override + String get viewCommentsLabel => 'Посмотреть комментарии'; + + @override + String get viewResultsLabel => 'Посмотреть результаты'; + + @override + String get endVoteLabel => 'Завершить опрос'; + + @override + String get pollResultsLabel => 'Результаты опроса'; + + @override + String get pollVotesLabel => 'Голоса'; + + @override + String showAllVotesLabel({int? count}) { + if (count == null) return 'Показать все голоса'; + return 'Показать все $count ${_plural(count, one: 'голос', few: 'голоса', many: 'голосов')}'; + } + + @override + String get viewAllLabel => 'Показать все'; + + @override + String voteCountLabel({int? count}) { + final c = count ?? 0; + if (c < 1) return '0 голосов'; + return '$c ${_plural(c, one: 'голос', few: 'голоса', many: 'голосов')}'; + } + + @override + String totalVoteCountLabel({int? count}) { + final c = count ?? 0; + if (c < 1) return 'всего 0 голосов'; + return 'всего $c ${_plural(c, one: 'голос', few: 'голоса', many: 'голосов')}'; + } + + @override + String get noPollVotesLabel => 'Сейчас нет голосов'; + + @override + String get loadingPollVotesError => 'Ошибка загрузки голосов'; + + @override + String get repliedToLabel => 'ответил(а):'; + + @override + String newThreadsLabel({required int count}) => + '$count ${_plural(count, one: 'новый тред', few: 'новых треда', many: 'новых тредов')}'; + + @override + String get loadingLabel => 'Загрузка...'; + + @override + String get slideToCancelLabel => 'Проведите, чтобы отменить'; + + @override + String get holdToRecordLabel => 'Удерживайте для записи. Отпустите для сохранения.'; + + @override + String get sendAnywayLabel => 'Всё равно отправить'; + + @override + String get moderatedMessageBlockedText => 'Сообщение заблокировано правилами модерации'; + + @override + String get moderationReviewModalTitle => 'Вы уверены?'; + + @override + String get moderationReviewModalDescription => + '''Подумайте, как ваш комментарий может повлиять на других, и обязательно следуйте нашим правилам сообщества.'''; + + @override + String get emptyMessagePreviewText => ''; + + @override + String get voiceRecordingText => 'Голосовое сообщение'; + + @override + String get audioAttachmentText => 'Аудио'; + + @override + String get imageAttachmentText => 'Изображение'; + + @override + String get videoAttachmentText => 'Видео'; + + @override + String get fileAttachmentText => 'Файл'; + + @override + String get linkAttachmentText => 'Ссылка'; + + @override + String filesAttachmentCountText(int count) => + count == 1 ? 'Файл' : '$count ${_plural(count, one: 'файл', few: 'файла', many: 'файлов')}'; + + @override + String photosAttachmentCountText(int count) => count == 1 ? 'Фото' : '$count фото'; + + @override + String videosAttachmentCountText(int count) => count == 1 ? 'Видео' : '$count видео'; + + @override + String get pollYouVotedText => 'Вы проголосовали'; + + @override + String pollSomeoneVotedText(String username) => '$username проголосовал(а)'; + + @override + String get pollYouCreatedText => 'Вы создали'; + + @override + String pollSomeoneCreatedText(String username) => '$username создал(а)'; + + @override + String get draftLabel => 'Черновик'; + + @override + String locationLabel({bool isLive = false}) { + if (isLive) return 'Трансляция геопозиции'; + return 'Геопозиция'; + } + + @override + String get noConversationsYetText => 'Пока нет бесед'; + + @override + String get replyToStartThreadText => 'Ответьте на сообщение, чтобы начать тред'; + + @override + String get sendMessageToStartConversationText => 'Отправьте сообщение, чтобы начать беседу'; + + @override + String get savedForLaterLabel => 'Сохранено на потом'; + + @override + String get repliedToThreadAnnotationLabel => 'Ответил(а) в треде'; + + @override + String get alsoSentInChannelAnnotationLabel => 'Также отправлено в канал'; + + @override + String get viewLabel => 'Просмотр'; + + @override + String get reminderSetLabel => 'Напоминание установлено'; + + @override + String reminderAtText(String time) => 'Сегодня в $time'; + + @override + String get createPollPromptLabel => 'Создайте опрос, и пусть все проголосуют!'; + + @override + String get takePhotoAndShareLabel => 'Сделайте фото и поделитесь'; + + @override + String get takeVideoAndShareLabel => 'Снимите видео и поделитесь'; + + @override + String get openCameraLabel => 'Открыть камеру'; + + @override + String get selectFilesToShareLabel => 'Выберите файлы, чтобы поделиться'; + + @override + String get openFilesLabel => 'Открыть файлы'; + + @override + String get unsupportedAttachmentLabel => 'Неподдерживаемое вложение'; + + @override + String get confirmLabel => 'ПОДТВЕРДИТЬ'; + + @override + String get emptyReactionsText => 'Пока нет реакций'; + + @override + String get loadingReactionsError => 'Ошибка загрузки реакций'; + + @override + String get tapToRemoveReactionLabel => 'Нажмите, чтобы убрать'; + + @override + String reactionsCountText(int count) => '$count ${_plural(count, one: 'реакция', few: 'реакции', many: 'реакций')}'; + + @override + String get justNowLabel => 'Только что'; + + @override + String replyToUserLabel(String userName) => 'Ответить $userName'; + + @override + String get multipleAnswersDescription => 'Выберите более одного варианта'; + + @override + String maximumVotesPerPersonDescription([Range? range]) { + final (:min, :max) = range ?? (min: 2, max: 10); + return 'Выберите от $min до $max вариантов'; + } + + @override + String get anonymousPollDescription => 'Скрыть, кто голосовал'; + + @override + String get suggestAnOptionDescription => 'Разрешить другим добавлять варианты'; + + @override + String get addACommentDescription => 'Разрешить другим оставлять комментарии'; +}