diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/pull_request_template.md similarity index 100% rename from .github/PULL_REQUEST_TEMPLATE/pull_request_template.md rename to .github/pull_request_template.md diff --git a/.github/workflows/issue_pr_management.yaml b/.github/workflows/issue_pr_management.yaml deleted file mode 100644 index bec4abca5..000000000 --- a/.github/workflows/issue_pr_management.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Close Inactive Issues And PRs -on: - schedule: - - cron: "30 1 * * *" - -jobs: - close-issues: - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - uses: actions/stale@v9 - with: - days-before-issue-stale: 120 - days-before-issue-close: 14 - stale-issue-label: "stale" - stale-issue-message: "This issue is stale because it has been open for 120 days with no activity." - close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." - stale-pr-message: "This pull request is stale because it has been open for 120 days with no activity." - close-pr-message: "This pull request was closed because it has been inactive for 14 days since being marked as stale." - days-before-pr-stale: 120 - days-before-pr-close: 14 - exempt-milestones: true - exempt-assignees: krille-chan - operations-per-run: 500 - repo-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 772e3f99e..69b9e0104 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -103,7 +103,7 @@ jobs: - run: cat .github/workflows/versions.env >> $GITHUB_ENV - uses: subosito/flutter-action@v2 with: - flutter-version: 3.19.6 # Workaround for not working on 3.22 + flutter-version: ${{ env.FLUTTER_VERSION }} cache: true - name: Install dependencies run: sudo apt-get update && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 libssl-dev -y diff --git a/.github/workflows/versions.env b/.github/workflows/versions.env index 4d10c42f4..a7af31db7 100644 --- a/.github/workflows/versions.env +++ b/.github/workflows/versions.env @@ -1,2 +1,2 @@ -FLUTTER_VERSION=3.22.2 +FLUTTER_VERSION=3.24.1 JAVA_VERSION=17 diff --git a/CHANGELOG.md b/CHANGELOG.md index 83968b329..273594b59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,114 @@ +## v1.22.0 + +FluffyChat v1.22.0 brings a new design for spaces, replaces the bottom navigation bar with filter chips and makes it finally possible to play ogg audio messages on iOS. A lot of other fixes and improvements have also been added to this release. + +FluffyChat also now uses the new authenticated media endpoints if the server supports Matrix v1.11 or +mentions the msc with the key `org.matrix.msc3916.stable` in the `unstable_features`. + +- build: (deps): bump docker/build-push-action from 5 to 6 (dependabot[bot]) +- build(deps): bump rexml from 3.2.8 to 3.3.3 in /ios (dependabot[bot]) +- build: Remove permissions for screensharing until it is fixed (Krille) +- build: Update android target sdk to 34 (Krille) +- build: Update dependencies after release (krille-chan) +- build: Update to Flutter 3.22.3 (krille-chan) +- build: Update to Matrix SDK 0.32.0 (Krille) +- chore: Bring back add to space feature (Krille) +- chore: Bring back navrail (krille-chan) +- chore: Bring back separate chat types (krille-chan) +- chore: Chat permissions page follow up (krille-chan) +- chore: Do not hide error on file sending (Krille) +- chore: Improved create group and space design (Krille) +- chore: Make VOIP plugin less noisy in logs (krille-chan) +- chore: Move default PR template to correct dir (krille-chan) +- chore: nicer bottom sheets (krille-chan) +- chore: Nicer empty chat list placeholder (krille-chan) +- chore: Polish public room bottom sheet (krille-chan) +- chore: Show short forms of months and week days in UI (krille-chan) +- chore: Sligthly improve chat permissions page design (krille-chan) +- design: Add snackbar with link to changelog on new version (Krille) +- docs: Update privacy policy (krille-chan) +- feat: Support for matrix auth media endpoints +- feat: Convert opus to aac on iOS before playing (Krille) +- feat: New spaces and chat list design (krille-chan) +- feat: Record voice message with opus/ogg if supported (Krille) +- feat: Send voice messages from web (Krille) +- fix: Display only available join rules (Krille) +- fix: Path correct userId to ignore list (krille-chan) +- fix: Scroll to event missing the position (Krille) +- Fix web base url and privacy url configuration processing (dlyrsk) +- refactor: Clean up some widths (krille-chan) +- refactor: Design polishment and better user viewer (Krille) +- refactor: Migrate android gradle plugin (Krille) +- refactor: Only initialize FlutterLocalNotificationsPlugin once (krille-chan) +- refactor: Recording dialog (Krille) +- Refactor: Reduce .of(context) calls theme (Thomas Klein Langenhorst) +- refactor: Use cached network image for mxc image uris (Krille) +- Translated using Weblate (Arabic) (kdh8219) +- Translated using Weblate (Arabic) (Rex_sa) +- Translated using Weblate (Basque) (kdh8219) +- Translated using Weblate (Basque) (xabirequejo) +- Translated using Weblate (Chinese (Simplified)) (kdh8219) +- Translated using Weblate (Chinese (Simplified)) (大王叫我来巡山) +- Translated using Weblate (Chinese (Traditional)) (kdh8219) +- Translated using Weblate (Chinese (Traditional)) (Lukas) +- Translated using Weblate (Chinese (Traditional)) (Ricky From Hong Kong) +- Translated using Weblate (Chinese (Traditional)) (不知火 Shiranui) +- Translated using Weblate (Croatian) (Milo Ivir) +- Translated using Weblate (Czech) (Anonymous) +- Translated using Weblate (Czech) (Michal Bedáň) +- Translated using Weblate (Dutch) (Guacamolie) +- Translated using Weblate (Dutch) (Jelv) +- Translated using Weblate (Dutch) (Thomas Klein Langenhorst) +- Translated using Weblate (Esperanto) (Anonymous) +- Translated using Weblate (Estonian) (kdh8219) +- Translated using Weblate (Estonian) (Priit Jõerüüt) +- Translated using Weblate (Finnish) (Anonymous) +- Translated using Weblate (French) (Sovkipyk) +- Translated using Weblate (Galician) (josé m) +- Translated using Weblate (German) (Christian) +- Translated using Weblate (German) (Pixelcode) +- Translated using Weblate (German) (tct123) +- Translated using Weblate (Hebrew) (Anonymous) +- Translated using Weblate (Indonesian) (Linerly) +- Translated using Weblate (Irish) (Anonymous) +- Translated using Weblate (Japanese) (Anonymous) +- Translated using Weblate (Korean) (kdh8219) +- Translated using Weblate (Lithuanian) (Anonymous) +- Translated using Weblate (Norwegian Bokmål) (Anonymous) +- Translated using Weblate (Persian) (Anonymous) +- Translated using Weblate (Portuguese (Portugal)) (Anonymous) +- Translated using Weblate (Romanian) (Anonymous) +- Translated using Weblate (Russian) (-) +- Translated using Weblate (Serbian) (Anonymous) +- Translated using Weblate (Slovenian) (Anonymous) +- Translated using Weblate (Spanish) (Anonymous) +- Translated using Weblate (Turkish) (kdh8219) +- Translated using Weblate (Turkish) (Oğuz Ersen) +- Translated using Weblate (Ukrainian) (Bezruchenko Simon) +- Translated using Weblate (Ukrainian) (Ihor Hordiichuk) + +## v1.21.2 +Updates the Matrix Dart SDK to fix some minor bugs. + +- Added translation using Weblate (Lojban) (Zig-Rust-Odin) +- build: Update matrix dart sdk (Krille) +- chore: Update last event after decryption (Krille) +- fix: Correctly localize time of date (Krille) +- refactor: Omit local types (Krille) +- Translated using Weblate (Arabic) (Rex_sa) +- Translated using Weblate (Basque) (xabirequejo) +- Translated using Weblate (Chinese (Simplified)) (大王叫我来巡山) +- Translated using Weblate (Croatian) (Milo Ivir) +- Translated using Weblate (Estonian) (Priit Jõerüüt) +- Translated using Weblate (Galician) (josé m) +- Translated using Weblate (Hungarian) (H Tamás) +- Translated using Weblate (Korean) (kdh8219) +- Translated using Weblate (Latvian) (Edgars Andersons) +- Translated using Weblate (Polish) (Eryk Michalak) +- Translated using Weblate (Portuguese (Brazil)) (lucasmz-dev) +- Translated using Weblate (Russian) (Nicholas Winterhalter) +- Translated using Weblate (Turkish) (Oğuz Ersen) + ## v1.21.1 - build: Update Matrix Dart SDK (Krille) - build: Update to Flutter 3.22.2 (krille-chan) diff --git a/PRIVACY.md b/PRIVACY.md index dd978f243..8c1ca45e5 100644 --- a/PRIVACY.md +++ b/PRIVACY.md @@ -3,31 +3,29 @@ FluffyChat is available on Android, iOS and as a web version. Desktop versions for Windows, Linux and macOS may follow. * [Matrix](#matrix) -* Sentry * [Database](#database) * [Encryption](#encryption) * [App Permissions](#app-permissions) * [Push Notifications](#push-notifications) -* [Stories](#stories) ## Matrix FluffyChat uses the Matrix protocol. This means that FluffyChat is just a client that can be connected to any compatible matrix server. The respective data protection agreement of the server selected by the user then applies. For convenience, one or more servers are set as default that the FluffyChat developers consider trustworthy. The developers of FluffyChat do not guarantee their trustworthiness. Before the first communication, users are informed which server they are connecting to. -FluffyChat only communicates with the selected server, with sentry.io if enabled and with [OpenStreetMap](https://openstreetmap.org) to display maps. +FluffyChat only communicates with the selected server and with [OpenStreetMap](https://openstreetmap.org) to display maps. More information is available at: [https://matrix.org](https://matrix.org) ## Database -FluffyChat caches some data received from the server in a local database on the device of the user. +FluffyChat caches some data received from the server in a local sqflite database on the device of the user. On web indexedDB is used. FluffyChat always tries to encrypt the database by using SQLCipher and stores the encryption key in the [Secure Storage](https://pub.dev/packages/flutter_secure_storage) of the device. -More information is available at: [https://pub.dev/packages/hive](https://pub.dev/packages/hive) +More information is available at: [https://pub.dev/packages/sqflite](https://pub.dev/packages/sqflite) and [https://pub.dev/packages/sqlcipher_flutter_libs](https://pub.dev/packages/sqlcipher_flutter_libs) ## Encryption All communication of substantive content between Fluffychat and any server is done in secure way, using transport encryption to protect it. -FluffyChat is able to use End-To-End-Encryption as a tech preview. +FluffyChat also uses End-To-End-Encryption by using [libolm](https://gitlab.matrix.org/matrix-org/olm) and enables it by default for private chats. ## App Permissions @@ -94,23 +92,3 @@ A typical push notification could look like this: ``` FluffyChat sets the `event_id_only` flag at the Matrix Server. This server is then responsible to send the correct data. - -## Stories - -FluffyChat supports stories which is a feature similar to WhatsApp status or Instagram stories. However it is just a different GUI for the same room-related communication. More information about the feature can be found here: - -https://github.com/krillefear/matrix-doc/blob/main/proposals/3588-stories-as-rooms.md - -Stories are basically: - -- End to end encrypted rooms -- Read-only rooms with only one admin who can post stuff (while there is no technical limitation to have multiple admins) - -By default: - -- The user has to invite all contacts manually to a story room -- The user can only invite contacts (matrix users the user shares a DM room with) to the story room -- The story room is created when the first story is posted -- User can mute and leave story rooms - -The user is informed in the app that in theory all contacts can see each other in the story room. The user must give consent here. However the user is at any time able to create a group chat and invite all of their contacts to this chat in any matrix client which has the same result. diff --git a/android/app/build.gradle b/android/app/build.gradle index 02dbcfefb..7362248d2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,3 +1,10 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" + //id "com.google.gms.google-services" +} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,11 +13,6 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -21,11 +23,6 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } -apply plugin: 'com.android.application' -apply plugin: 'com.google.gms.google-services' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { @@ -44,7 +41,10 @@ android { } defaultConfig { + // #Pangea + // applicationId "chat.fluffy.fluffychat" applicationId "com.talktolearn.chat" + // Pangea# minSdkVersion 21 targetSdkVersion 34 versionCode flutterVersionCode.toInteger() @@ -66,8 +66,7 @@ android { buildTypes { debug { signingConfig signingConfigs.debug - applicationIdSuffix "" - versionNameSuffix "" + versionNameSuffix "-debug" } release { signingConfig signingConfigs.release @@ -87,9 +86,6 @@ flutter { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" //implementation 'com.google.firebase:firebase-messaging:19.0.1' // Workaround for https://github.com/microg/android_packages_apps_GmsCore/issues/313#issuecomment-617651698 implementation 'androidx.multidex:multidex:2.0.1' -} - -//apply plugin: 'com.google.gms.google-services' +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9e52b2a59..2eb411a23 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -18,14 +18,12 @@ - - diff --git a/android/build.gradle b/android/build.gradle index 94a04851d..8f31e8caf 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,17 +1,3 @@ -buildscript { - ext.kotlin_version = '1.8.0' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.13' - } -} - allprojects { repositories { google() @@ -29,4 +15,4 @@ subprojects { tasks.register("clean", Delete) { delete rootProject.buildDir -} +} \ No newline at end of file diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bcf0..b2fd960a7 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,26 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.1.2" apply false + id "org.jetbrains.kotlin.android" version "1.8.0" apply false + // id "com.google.gms.google-services" version "4.3.8" apply false +} + +include ":app" \ No newline at end of file diff --git a/assets/l10n/intl_ar.arb b/assets/l10n/intl_ar.arb index 8cd5a4080..7adb678b1 100644 --- a/assets/l10n/intl_ar.arb +++ b/assets/l10n/intl_ar.arb @@ -736,7 +736,7 @@ "type": "text", "placeholders": {} }, - "oopsSomethingWentWrong": "عذراً، هناك خطأ ما…", + "oopsSomethingWentWrong": "عفوًا، حدث خطأ ما…", "@oopsSomethingWentWrong": { "type": "text", "placeholders": {} @@ -1821,7 +1821,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "مستوى الأذونات الإفتراضي", + "defaultPermissionLevel": "مستوى الأذونات الافتراضية للمستخدمين الجدد", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -2260,7 +2260,7 @@ }, "jump": "قفز", "@jump": {}, - "report": "التقرير", + "report": "تقرير", "@report": {}, "noKeyForThisMessage": "يمكن أن يحدث هذا إذا تم إرسال الرسالة قبل تسجيل الدخول إلى حسابك على هذا الجهاز.\n\nمن الممكن أيضا أن يكون المرسل قد حظر جهازك أو حدث خطأ ما في الاتصال بالإنترنت.\n\nهل يمكنك قراءة الرسالة في جلسة أخرى؟ ثم يمكنك نقل الرسالة منه! انتقل إلى الإعدادات > الأجهزة وتأكد من أن أجهزتك قد تحققت من بعضها البعض. عندما تفتح الغرفة في المرة التالية وتكون كلتا الجلستين في المقدمة ، سيتم إرسال المفاتيح تلقائيا.\n\nألا تريد أن تفقد المفاتيح عند تسجيل الخروج أو تبديل الأجهزة؟ تأكد من تمكين النسخ الاحتياطي للدردشة في الإعدادات.", "@noKeyForThisMessage": {}, @@ -2706,5 +2706,102 @@ "searchMore": "ابحث أكثر...", "@searchMore": {}, "gallery": "المعرض", - "@gallery": {} + "@gallery": {}, + "swipeRightToLeftToReply": "اسحب من اليمين إلى اليسار للرد", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "false", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "countChatsAndCountParticipants": "{chats} دردشات و {participants} مشاركين", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "noMoreChatsFound": "لم يتم العثور على دردشات...", + "@noMoreChatsFound": {}, + "joinedChats": "انضم إلى الدردشة", + "@joinedChats": {}, + "unread": "غير المقروءة", + "@unread": {}, + "space": "المساحة", + "@space": {}, + "spaces": "المساحات", + "@spaces": {}, + "markAsUnread": "تحديد كغير مقروء", + "@markAsUnread": {}, + "goToSpace": "انتقل إلى المساحة: {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "userLevel": "{level} - مستخدم", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - مشرف", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - مدير", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeGeneralChatSettings": "تغيير إعدادات الدردشة العامة", + "@changeGeneralChatSettings": {}, + "inviteOtherUsers": "دعوة مستخدمين آخرين إلى هذه الدردشة", + "@inviteOtherUsers": {}, + "changeTheChatPermissions": "تغيير أذونات الدردشة", + "@changeTheChatPermissions": {}, + "changeTheVisibilityOfChatHistory": "تغيير رؤية سجل الدردشة", + "@changeTheVisibilityOfChatHistory": {}, + "changeTheCanonicalRoomAlias": "تغيير عنوان الدردشة العامة الرئيسي", + "@changeTheCanonicalRoomAlias": {}, + "sendRoomNotifications": "إرسال إشعارات @room", + "@sendRoomNotifications": {}, + "changeTheDescriptionOfTheGroup": "تغيير وصف الدردشة", + "@changeTheDescriptionOfTheGroup": {}, + "invitedBy": "📩 تمت دعوته من قبل {user}", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "chatPermissionsDescription": "‪حدد مستوى الصلاحية الضروري لإجراءات معينة في هذه الدردشة. عادة ما تمثل مستويات الصلاحية 0 و 50 و 100 المستخدمين والمشرفين ولكن أي تدرج ممكن.", + "@chatPermissionsDescription": {}, + "changelog": "سجل التغييرات", + "@changelog": {}, + "updateInstalled": "تم تثبيت🎉 تحديث {version}!", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "sendCanceled": "تم إلغاء الإرسال", + "@sendCanceled": {}, + "noChatsFoundHere": "لم يتم العثور على دردشات هنا حتى الآن. ابدأ محادثة جديدة مع شخص ما باستخدام الزر أدناه. ⤵️", + "@noChatsFoundHere": {}, + "loginWithMatrixId": "تسجيل الدخول باستخدام معرف ماتريكس", + "@loginWithMatrixId": {}, + "discoverHomeservers": "اكتشف الخوادم المنزلية", + "@discoverHomeservers": {}, + "whatIsAHomeserver": "ما هو خادم المنزل ؟", + "@whatIsAHomeserver": {}, + "homeserverDescription": "يتم تخزين جميع بياناتك على خادم المنزل، تمامًا مثل مزود خدمة البريد الإلكتروني. يمكنك اختيار خادم البيت الذي تريد استخدامه، بينما لا يزال بإمكانك التواصل مع الجميع. اعرف المزيد على https://matrix.org.", + "@homeserverDescription": {}, + "doesNotSeemToBeAValidHomeserver": "لا يبدو أنه خادم منزلي متوافق. عنوان URL غير صحيح ؟", + "@doesNotSeemToBeAValidHomeserver": {} } diff --git a/assets/l10n/intl_cs.arb b/assets/l10n/intl_cs.arb index c6a4820c4..73ed1592a 100644 --- a/assets/l10n/intl_cs.arb +++ b/assets/l10n/intl_cs.arb @@ -2349,48 +2349,11 @@ "count": {} } }, - "@reportErrorDescription": {}, - "@banUserDescription": {}, - "@removeDevicesDescription": {}, - "@unbanUserDescription": {}, - "@pushNotificationsNotAvailable": {}, - "@makeAdminDescription": {}, - "@archiveRoomDescription": {}, - "@invalidInput": {}, - "@report": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@inviteGroupChat": {}, - "@invitePrivateChat": {}, - "@learnMore": {}, - "@roomUpgradeDescription": {}, - "@pleaseEnterANumber": {}, "emoteKeyboardNoRecents": "Naposledy použité emoce se zobrazí zde...", "@emoteKeyboardNoRecents": { "type": "text", "placeholders": {} }, - "@kickUserDescription": {}, - "@invite": {}, - "@indexedDbErrorLong": {}, - "@callingAccount": {}, - "@enterSpace": {}, - "@noKeyForThisMessage": {}, - "@readUpToHere": {}, - "@appearOnTopDetails": {}, - "@enterRoom": {}, - "@hideUnimportantStateEvents": {}, - "@noBackupWarning": {}, - "@indexedDbErrorTitle": {}, "appLockDescription": "Zamknout aplikaci pomocí PIN kódu když není používána", "@appLockDescription": {}, "globalChatId": "Globální ID chatu", @@ -2404,5 +2367,17 @@ "accessAndVisibilityDescription": "Kdo se může připojit a najít tuto konverzaci.", "@accessAndVisibilityDescription": {}, "customEmojisAndStickersBody": "Přidat nebo sdílet vlastní emoji nebo nálepky, které mohou být použité v konverzaci.", - "@customEmojisAndStickersBody": {} + "@customEmojisAndStickersBody": {}, + "swipeRightToLeftToReply": "Potáhněte z prava do leva pro odpověď", + "@swipeRightToLeftToReply": {}, + "countChatsAndCountParticipants": "{chats} konverzaci a {participants} účastníci", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "noMoreChatsFound": "Žádné další konverzace nalezeny...", + "@noMoreChatsFound": {} } diff --git a/assets/l10n/intl_de.arb b/assets/l10n/intl_de.arb index adf2d99d0..f9321f156 100644 --- a/assets/l10n/intl_de.arb +++ b/assets/l10n/intl_de.arb @@ -1,6 +1,10 @@ { "@@locale": "de", "@@last_modified": "2021-08-14 12:41:10.119255", + "alwaysUse24HourFormat": "true", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, "about": "Über", "@about": { "type": "text", @@ -356,7 +360,7 @@ "type": "text", "description": "Usage hint for the command /invite" }, - "commandHint_join": "Betrete den ausgewählten Raum", + "commandHint_join": "Betritt den ausgewählten Raum", "@commandHint_join": { "type": "text", "description": "Usage hint for the command /join" @@ -554,7 +558,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "Standardberechtigungsstufe", + "defaultPermissionLevel": "Standardberechtigungsstufe für neue Benutzer", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -1080,7 +1084,7 @@ "type": "text", "placeholders": {} }, - "noGoogleServicesWarning": "Firebase Cloud Messaging scheint auf deinem Gerät nicht verfügbar zu sein. Um trotzdem Push-Benachrichtigungen zu erhalten, empfehlen wir die Installation von ntfy. Mit ntfy oder einem anderen Unified Push Anbieter kannst du Push-Benachrichtigungen datensicher empfangen. Du kannst ntfy im PlayStore oder bei F-Droid herunterladen.", + "noGoogleServicesWarning": "Firebase Cloud Messaging scheint auf deinem Gerät nicht verfügbar zu sein. Um trotzdem Push-Benachrichtigungen zu erhalten, empfehlen wir die Installation von ntfy. Mit ntfy oder einem anderen Unified-Push-Anbieter kannst du Push-Benachrichtigungen datensicher empfangen. Du kannst ntfy im PlayStore oder bei F-Droid herunterladen.", "@noGoogleServicesWarning": { "type": "text", "placeholders": {} @@ -1663,7 +1667,7 @@ "type": "text", "placeholders": {} }, - "tryToSendAgain": "Nochmal versuchen zu senden", + "tryToSendAgain": "Noch mal versuchen zu senden", "@tryToSendAgain": { "type": "text", "placeholders": {} @@ -1708,7 +1712,7 @@ "type": "text", "placeholders": {} }, - "unpin": "Abpinnen", + "unpin": "Nicht mehr anpinnen", "@unpin": { "type": "text", "placeholders": {} @@ -1961,7 +1965,7 @@ "@start": {}, "repeatPassword": "Passwort wiederholen", "@repeatPassword": {}, - "commandHint_dm": "Starte einen direkten Chat\nBenutze --no-encryption um die Verschlüsselung auszuschalten", + "commandHint_dm": "Starte einen direkten Chat\nBenutze --no-encryption, um die Verschlüsselung auszuschalten", "@commandHint_dm": { "type": "text", "description": "Usage hint for the command /dm" @@ -1976,7 +1980,7 @@ "type": "text", "description": "Usage hint for the command /clearcache" }, - "commandHint_create": "Erstelle ein leeren Gruppenchat\nBenutze --no-encryption um die Verschlüsselung auszuschalten", + "commandHint_create": "Erstelle ein leeren Gruppenchat\nBenutze --no-encryption, um die Verschlüsselung auszuschalten", "@commandHint_create": { "type": "text", "description": "Usage hint for the command /create" @@ -2009,7 +2013,7 @@ "@videoCallsBetaWarning": {}, "emailOrUsername": "E-Mail oder Benutzername", "@emailOrUsername": {}, - "unsupportedAndroidVersionLong": "Diese Funktion erfordert eine neuere Android-Version. Bitte suche nach Updates oder Lineage OS-Unterstützung.", + "unsupportedAndroidVersionLong": "Diese Funktion erfordert eine neuere Android-Version. Bitte suche nach Updates oder prüfe die Lineage-OS-Unterstützung.", "@unsupportedAndroidVersionLong": {}, "experimentalVideoCalls": "Experimentelle Videoanrufe", "@experimentalVideoCalls": {}, @@ -2147,7 +2151,7 @@ "@saveKeyManuallyDescription": {}, "hydrateTorLong": "Hast du deine Sitzung das letzte Mal auf TOR exportiert? Importiere sie schnell und chatte weiter.", "@hydrateTorLong": {}, - "pleaseEnterRecoveryKey": "Bitte gebe deinen Wiederherstellungsschlüssel ein:", + "pleaseEnterRecoveryKey": "Bitte gib deinen Wiederherstellungsschlüssel ein:", "@pleaseEnterRecoveryKey": {}, "countFiles": "{count} Dateien", "@countFiles": { @@ -2261,7 +2265,7 @@ "senderName": {} } }, - "commandHint_googly": "Googly Eyes senden", + "commandHint_googly": "Glupschaugen senden", "@commandHint_googly": {}, "disableEncryptionWarning": "Aus Sicherheitsgründen können Sie die Verschlüsselung in einem Chat nicht deaktivieren, wo sie zuvor aktiviert wurde.", "@disableEncryptionWarning": {}, @@ -2269,7 +2273,7 @@ "@reopenChat": {}, "fileIsTooBigForServer": "Der Server meldet, dass die Datei zu groß ist für eine Übermittlung ist.", "@fileIsTooBigForServer": {}, - "noBackupWarning": "Achtung! Ohne Aktivierung des Chat-Backups verlierst du den Zugriff auf deine verschlüsselten Nachrichten. Vor dem Ausloggen wird dringend empfohlen den Chat-Backup zu aktivieren.", + "noBackupWarning": "Achtung! Ohne Aktivierung des Chat-Backups verlierst du den Zugriff auf deine verschlüsselten Nachrichten. Vor dem Ausloggen wird dringend empfohlen, das Chat-Backup zu aktivieren.", "@noBackupWarning": {}, "noOtherDevicesFound": "Keine anderen Geräte anwesend", "@noOtherDevicesFound": {}, @@ -2585,7 +2589,7 @@ "sender": {} } }, - "verifyOtherDeviceDescription": "Wenn Sie ein anderes Gerät verifizieren, können diese Geräteschlüssel austauschen, was Ihre Sicherheit insgesamt erhöht. 💪 Wenn Sie eine Verifizierung starten, erscheint ein Pop-up in der App auf beiden Geräten. Dort sehen Sie dann eine Reihe von Emojis oder Zahlen, die Sie miteinander vergleichen müssen. Am besten hältst du beide Geräte bereit, bevor du die Verifizierung startest. 🤳", + "verifyOtherDeviceDescription": "Wenn Sie ein anderes Gerät verifizieren, können diese Geräteschlüssel austauschen, was Ihre Sicherheit insgesamt erhöht. 💪 Wenn Sie eine Verifizierung starten, erscheint ein Pop-up in der App auf beiden Geräten. Dort sehen Sie dann eine Reihe von Emojis oder Zahlen, die Sie miteinander vergleichen müssen. Am besten halten Sie beide Geräte bereit, bevor Sie die Verifizierung starten. 🤳", "@verifyOtherDeviceDescription": {}, "presenceStyle": "Statusmeldungen:", "@presenceStyle": { @@ -2706,5 +2710,88 @@ } }, "searchMore": "Weiter suchen ...", - "@searchMore": {} + "@searchMore": {}, + "unread": "Ungelesen", + "@unread": {}, + "noMoreChatsFound": "Keine weiteren Chats gefunden ...", + "@noMoreChatsFound": {}, + "joinedChats": "Beigetretene Chats", + "@joinedChats": {}, + "space": "Space", + "@space": {}, + "spaces": "Spaces", + "@spaces": {}, + "goToSpace": "Geh zum Space: {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "Als ungelesen markieren", + "@markAsUnread": {}, + "swipeRightToLeftToReply": "Wische von rechts nach links zum Antworten", + "@swipeRightToLeftToReply": {}, + "countChatsAndCountParticipants": "{chats} Chats und {participants} Teilnehmer", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "changeGeneralChatSettings": "Allgemeine Chat-Einstellungen ändern", + "@changeGeneralChatSettings": {}, + "userLevel": "{level} - Benutzer", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - Moderator", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeTheChatPermissions": "Ändere die Chat-Berechtigungen", + "@changeTheChatPermissions": {}, + "changeTheVisibilityOfChatHistory": "Wechsele die Sichtbarkeit der Chat-Historie", + "@changeTheVisibilityOfChatHistory": {}, + "chatPermissionsDescription": "Definieren Sie, welche Befugnisstufe für bestimmte Aktionen in diesem Chat erforderlich ist. Die Befugnisstufen 0, 50 und 100 stehen üblicherweise für Benutzer, Moderatoren und Admins, aber jede Abstufung ist möglich.", + "@chatPermissionsDescription": {}, + "invitedBy": "📩 Eingeladen von {user}", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "adminLevel": "{level} - Administrator", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "inviteOtherUsers": "Lade andere Benutzer in diesen Chat ein", + "@inviteOtherUsers": {}, + "changeTheCanonicalRoomAlias": "Ändern der Hauptadresse für den öffentlichen Chat", + "@changeTheCanonicalRoomAlias": {}, + "sendRoomNotifications": "Senden Sie eine @room-Benachrichtigung", + "@sendRoomNotifications": {}, + "changeTheDescriptionOfTheGroup": "Ändern Sie die Beschreibung des Chats", + "@changeTheDescriptionOfTheGroup": {}, + "updateInstalled": "🎉 Update {version} installiert!", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "changelog": "Änderungsprotokoll", + "@changelog": {}, + "sendCanceled": "Senden abgebrochen", + "@sendCanceled": {}, + "noChatsFoundHere": "Hier wurden noch keine Chats gefunden. Starten Sie einen neuen Chat mit jemandem, indem Sie die Schaltfläche unten verwenden. ⤵️", + "@noChatsFoundHere": {} } diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index ba07fea9f..6312008d6 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -1,6 +1,10 @@ { "@@locale": "en", "@@last_modified": "2021-08-14 12:38:37.885451", + "alwaysUse24HourFormat": "false", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, "repeatPassword": "Repeat password", "@repeatPassword": {}, "notAnImage": "Not an image file.", @@ -197,6 +201,20 @@ "supportedVersions": {} } }, + "countChatsAndCountParticipants": "{chats} chats and {participants} participants", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "noMoreChatsFound": "No more chats found...", + "noChatsFoundHere": "No chats found here yet. Start a new chat with someone by using the button below. ⤵️", + "joinedChats": "Joined chats", + "unread": "Unread", + "space": "Space", + "spaces": "Spaces", "banFromChat": "Ban from chat", "@banFromChat": { "type": "text", @@ -660,7 +678,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "Default permission level", + "defaultPermissionLevel": "Default permission level for new users", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -3885,7 +3903,7 @@ "define": "Define", "listen": "Listen", "addConversationBot": "Enable Conversation Bot", - "addConversationBotDesc": "Add a bot to this group chat", + "addConversationBotDesc": "Add a bot to this chat", "convoBotSettingsTitle": "Conversation Bot Settings", "convoBotSettingsDescription": "Edit conversation topic and difficulty", "enterAConversationTopic": "Enter a conversation topic", @@ -3950,7 +3968,7 @@ "seeOptions": "See options", "continuedWithoutSubscription": "Continue without subscribing", "trialPeriodExpired": "Your trial period has expired", - "selectToDefine": "Double click a word to see its definition!", + "selectToDefine": "Highlight a word or phrase to see its definition!", "translations": "translations", "messageAudio": "message audio", "definitions": "definitions", @@ -4095,11 +4113,11 @@ "placeholders": {} }, "addChatToSpaceDesc": "Adding a chat to a space will make the chat appear within the space for students and give them access.", - "addSpaceToSpaceDesc": "Adding a space to another space will make the child space appear within the parent space for students and give them access.", + "addSpaceToSpaceDesc": "Adding a sub space to space will make the sub space appear in the main space's chat list.", "spaceAnalytics": "Space Analytics", "changeAnalyticsLanguage": "Change Analytics Language", "suggestToSpace": "Suggest this space", - "suggestToSpaceDesc": "Suggested spaces will appear in the chat lists for their parent spaces", + "suggestToSpaceDesc": "Suggested sub spaces will appear in their main space's chat list", "practice": "Practice", "noLanguagesSet": "No languages set", "noActivitiesFound": "No practice activities found for this message", @@ -4152,7 +4170,63 @@ "createChat": "Create chat", "error520Title": "Please try again.", "error520Desc": "Sorry, we could not understand your message...", + "wordsUsed": "Words Used", + "errorTypes": "Error Types", + "level": "Level", + "canceledSend": "Canceled send", + "morphsUsed": "Morphs Used", "translationChoicesBody": "Click and hold an option for a hint.", "sendCanceled": "Sending canceled", - "space": "Space" + "goToSpace": "Go to space: {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "Mark as unread", + "userLevel": "{level} - User", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - Moderator", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - Admin", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeGeneralChatSettings": "Change general chat settings", + "inviteOtherUsers": "Invite other users to this chat", + "changeTheChatPermissions": "Change the chat permissions", + "changeTheVisibilityOfChatHistory": "Change the visibility of the chat history", + "changeTheCanonicalRoomAlias": "Change the main public chat address", + "sendRoomNotifications": "Send a @room notifications", + "changeTheDescriptionOfTheGroup": "Change the description of the chat", + "chatPermissionsDescription": "Define which power level is necessary for certain actions in this chat. The power levels 0, 50 and 100 are usually representing users, moderators and admins, but any gradation is possible.", + "updateInstalled": "🎉 Update {version} installed!", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "changelog": "Changelog", + "loginWithMatrixId": "Login with Matrix-ID", + "discoverHomeservers": "Discover homeservers", + "whatIsAHomeserver": "What is a homeserver?", + "homeserverDescription": "All your data is stored on the homeserver, just like an email provider. You can choose which homeserver you want to use, while you can still communicate with everyone. Learn more at at https://matrix.org.", + "doesNotSeemToBeAValidHomeserver": "Doesn't seem to be a compatible homeserver. Wrong URL?", + "grammar": "Grammar", + "contactHasBeenInvitedToTheChat": "Contact has been invited to the chat", + "inviteChat": "📨 Invite chat", + "chatName": "Chat name" } \ No newline at end of file diff --git a/assets/l10n/intl_eo.arb b/assets/l10n/intl_eo.arb index 2cda9beb9..872e72ec0 100644 --- a/assets/l10n/intl_eo.arb +++ b/assets/l10n/intl_eo.arb @@ -1,2234 +1,1906 @@ { - "@@last_modified": "2021-08-14 12:41:10.107750", - "about": "Prio", - "@about": { - "type": "text", - "placeholders": {} - }, - "accept": "Akcepti", - "@accept": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "{username} akceptis la inviton", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "Konto", - "@account": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "{username} aktivigis tutvojan ĉifradon", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "addEmail": "Aldoni retpoŝtadreson", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "admin": "Administranto", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "kromnomo", - "@alias": { - "type": "text", - "placeholders": {} - }, - "all": "Ĉio", - "@all": { - "type": "text", - "placeholders": {} - }, - "allChats": "Ĉiuj babiloj", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "{senderName} respondis la vokon", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "Ĉiu ajn povas aliĝi", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "appLock": "Ŝlosado", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "archive": "Arĥivo", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "Ĉu gastoj rajtas aliĝi", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "Ĉu vi certas?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "areYouSureYouWantToLogout": "Ĉu vi certe volas adiaŭi?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "Por ke vi povu kontroli (subskribi) la alian personon, bonvolu enigi pasfrazon de via sekreta deponejo aŭ vian rehavan ŝlosilon.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "Ĉu akcepti ĉi tiun kontrolpeton de {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "badServerLoginTypesException": "La hejmservilo subtenas la jenajn specojn de salutoj:\n{serverVersions}\nSed ĉi tiu aplikaĵo subtenas nur:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "badServerVersionsException": "La hejmservilo subtenas la jenajn version de la specifaĵo:\n{serverVersions}\nSed ĉi tiu aplikaĵo subtenas nur {supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "banFromChat": "Forbari de babilo", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "Forbarita", - "@banned": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "{username} forbaris uzanton {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "blockDevice": "Bloki aparaton", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "Blokita", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "botMessages": "Mesaĝoj de robotoj", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "cancel": "Nuligi", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "cantOpenUri": "Ne povis malfermi URI {uri}", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "changeDeviceName": "Ŝanĝi nomon de aparato", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "{username} ŝanĝis bildon de la babilo", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatDescriptionTo": "{username} ŝanĝis priskribon de la babilo al: «{description}»", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheChatNameTo": "{username} ŝanĝis nomon de la babilo al: «{chatname}»", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheChatPermissions": "{username} ŝanĝis permesojn pri la babilo", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "{username} ŝanĝis sian prezentan nomon al: {username}", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRules": "{username} ŝanĝis regulojn pri aliro de gastoj", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} ŝanĝis regulojn pri aliro de gastoj al: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheHistoryVisibility": "{username} ŝanĝis videblecon de la historio", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "{username} ŝanĝis videblecon de la historio al: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username} ŝanĝis regulojn pri aliĝado", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "{username} ŝanĝis regulojn pri aliĝado al: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheProfileAvatar": "{username} ŝanĝis sian profilbildon", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "{username} ŝanĝis la kromnomojn de la ĉambro", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomInvitationLink": "{username} ŝanĝis la invitan ligilon", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changePassword": "Ŝanĝi pasvorton", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "changeTheHomeserver": "Ŝanĝi hejmservilon", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "Ŝanĝu la haŭton", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "Ŝanĝi nomon de la grupo", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "Ŝanĝi vian profilbildon", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "La ĉifrado estas difektita", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chat": "Babilo", - "@chat": { - "type": "text", - "placeholders": {} - }, - "chatBackup": "Savkopiado de babilo", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "Via savkopio de babilo estas sekurigita per sekureca ŝlosilo. Bonvolu certigi, ke vi ne perdos ĝin.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "Detaloj pri babilo", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chats": "Babiloj", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "Elektu fortan pasvorton", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "Vakigi arĥivon", - "@clearArchive": {}, - "close": "Fermi", - "@close": { - "type": "text", - "placeholders": {} - }, - "commandHint_ban": "Forbari la donitan uzanton de ĉi tiu ĉambro", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_html": "Sendi tekston formatan je HTML", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "Inviti la donitan uzanton al ĉi tiu ĉambro", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_join": "Aliĝi al la donita ĉambro", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_kick": "Forigi la donitan uzanton de ĉi tiu ĉambro", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_leave": "Foriri de ĉi tiu ĉambro", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_me": "Priskribu vian agon", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "commandHint_myroomavatar": "Agordi vian profilbildon por ĉi tiu ĉambro (laŭ mxc-uri)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_myroomnick": "Agordi vian prezentan nomon en ĉi tiu ĉambro", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_op": "Agordi povnivelon de la donita uzanto (implicite: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_plain": "Sendi senformatan tekston", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_react": "Sendi respondon kiel reagon", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandHint_unban": "Malforbari la donitan uzanton de ĉi tiu ĉambro", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "commandInvalid": "Nevalida ordono", - "@commandInvalid": { - "type": "text" - }, - "commandMissing": "{command} ne estas ordono.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "compareEmojiMatch": "Komparu kaj certigu, ke la jenaj bildosignoj samas en ambaŭ aparatoj:", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Komparu kaj certigu, ke la jenaj numeroj samas en ambaŭ aparatoj:", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "configureChat": "Agordi babilon", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "confirm": "Konfirmi", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "connect": "Konektiĝi", - "@connect": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "Kontakto invitiĝis al la grupo", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "Enhavas prezentan nomon", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "Enhavas uzantonomon", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "La enhavo raportiĝis al la administrantoj de la servilo", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "Kopiite al tondujo", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "copy": "Kopii", - "@copy": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "Kopii al tondujo", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Ne povis malĉifri mesaĝon: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "countParticipants": "{count} partoprenantoj", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "create": "Krei", - "@create": { - "type": "text", - "placeholders": {} - }, - "createdTheChat": "{username} kreis la babilon", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "createNewSpace": "Nova aro", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "currentlyActive": "Nun aktiva", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "Malhela", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "dateWithoutYear": "{day}a de la {month}a", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateWithYear": "{day}a de la {month}a de {year}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "deactivateAccountWarning": "Ĉi tio malaktivigos vian konton de uzanto. Ne eblas tion malfari! Ĉu certe vi certas?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "Norma nivelo de permesoj", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "delete": "Forigi", - "@delete": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "Forigi konton", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "Forigi mesaĝon", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "device": "Aparato", - "@device": { - "type": "text", - "placeholders": {} - }, - "deviceId": "Identigilo de aparato", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "Aparatoj", - "@devices": { - "type": "text", - "placeholders": {} - }, - "directChats": "Rektaj babiloj", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "Prezenta nomo ŝanĝiĝis", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "Elŝuti dosieron", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "edit": "Redakti", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "Redakti blokitajn servilojn", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "Redakti prezentan nomon", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "Ŝanĝi kromnomojn de ĉambro", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "Redakti bildon de ĉambro", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Mieneto jam ekzistas!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "Nevalida mallongigo de mieneto!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "Mienetaroj por la ĉambro", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Agordoj pri mienetoj", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "emoteShortcode": "Mallongigo de mieneto", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Vi devas elekti mallongigon de mieneto kaj bildon!", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "Malplena babilo", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "Ŝalti mienetaron ĉie", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "Ŝalti ĉifradon", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "enableEncryptionWarning": "Vi ne povos malŝalti la ĉifradon. Ĉu vi certas?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "encrypted": "Ĉifrite", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "encryption": "Ĉifrado", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "encryptionNotEnabled": "Ĉifrado ne estas ŝaltita", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "{senderName} finis la vokon", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "enterAnEmailAddress": "Enigu retpoŝtadreson", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "enterYourHomeserver": "Enigu vian hejmservilon", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "errorObtainingLocation": "Eraris akirado de loko: {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "everythingReady": "Ĉio pretas!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "Tre ofenda", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "fileName": "Dosiernomo", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "fontSize": "Grandeco de tiparo", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "forward": "Plusendi", - "@forward": { - "type": "text", - "placeholders": {} - }, - "fromJoining": "Ekde aliĝo", - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "fromTheInvitation": "Ekde la invito", - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "goToTheNewRoom": "Iri al la nova ĉambro", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "group": "Grupo", - "@group": { - "type": "text", - "placeholders": {} - }, - "groupIsPublic": "Grupo estas publika", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "groups": "Grupoj", - "@groups": { - "type": "text", - "placeholders": {} - }, - "groupWith": "Grupo kun {displayname}", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "guestsAreForbidden": "Gastoj estas malpermesitaj", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "Gastoj povas aliĝi", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "hasWithdrawnTheInvitationFor": "{username} nuligis la inviton por {targetName}", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "help": "Helpo", - "@help": { - "type": "text", - "placeholders": {} - }, - "hideRedactedEvents": "Kaŝi obskurigitajn eventojn", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "Kaŝi nekonatajn eventojn", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "howOffensiveIsThisContent": "Kiel ofenda estas ĉi tiu enhavo?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "id": "Identigilo", - "@id": { - "type": "text", - "placeholders": {} - }, - "identity": "Identeco", - "@identity": { - "type": "text", - "placeholders": {} - }, - "ignore": "Malatenti", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "Malatentitaj uzantoj", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "Mi klakis la ligilon", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "incorrectPassphraseOrKey": "Neĝusta pasfrazo aŭ rehava ŝlosilo", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "Neofenda", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "Inviti kontakton", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "Inviti kontakton al {groupName}", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "invited": "Invitita", - "@invited": { - "type": "text", - "placeholders": {} - }, - "invitedUser": "{username} invitis uzanton {targetName}", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "invitedUsersOnly": "Nur invititoj", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "inviteForMe": "Invito por mi", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "inviteText": "{username} invitis vin al FluffyChat. \n1. Instalu la aplikaĵon FluffyChat: https://fluffychat.im \n2. Registriĝu aŭ salutu \n3. Malfermu la invitan ligilon: {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "isTyping": "tajpas…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "joinedTheChat": "{username} aliĝis al la babilo", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "joinRoom": "Aliĝi al ĉambro", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "kicked": "{username} forpelis uzanton {targetName}", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickedAndBanned": "{username} forpelis kaj forbaris uzanton {targetName}", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickFromChat": "Forpeli de babilo", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "lastActiveAgo": "Lastafoje aktiva: {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "leave": "Foriri", - "@leave": { - "type": "text", - "placeholders": {} - }, - "leftTheChat": "Foriris de la ĉambro", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "license": "Permesilo", - "@license": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "Hela", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "loadCountMoreParticipants": "Enlegi {count} pliajn partoprenantojn", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "loadingPleaseWait": "Enlegante… bonvolu atendi.", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "loadMore": "Enlegi pli…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "login": "Saluti", - "@login": { - "type": "text", - "placeholders": {} - }, - "logInTo": "Saluti servilon {homeserver}", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "logout": "Adiaŭi", - "@logout": { - "type": "text", - "placeholders": {} - }, - "memberChanges": "Ŝanĝoj de anoj", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "mention": "Mencii", - "@mention": { - "type": "text", - "placeholders": {} - }, - "messages": "Mesaĝoj", - "@messages": { - "type": "text", - "placeholders": {} - }, - "moderator": "Reguligisto", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "muteChat": "Silentigi babilon", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "Bonvolu scii, ke vi ankoraŭ bezonas la programon Pantalaimon por uzi tutvojan ĉifradon.", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "newChat": "Nova babilo", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "Nova mesaĝo en FluffyChat", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "newVerificationRequest": "Nova kontrolpeto!", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "next": "Sekva", - "@next": { - "type": "text", - "placeholders": {} - }, - "no": "Ne", - "@no": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "Neniu konekto al la servilo", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "noEmotesFound": "Neniuj mienetoj troviĝis. 😕", - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "Vi nur povas aktivigi ĉifradon kiam la ĉambro ne plu estas publike alirebla.", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "noGoogleServicesWarning": "Ŝajnas, ke via telefono ne havas servojn de Google. Tio estas bona decido por via privateco! Por ricevadi pasivajn sciigojn en FluffyChat, ni rekomendas, ke vi uzu la https://microg.org/ aŭ https://unifiedpush.org/.", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "none": "Neniu", - "@none": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "Vi ankoraŭ ne aldonis manieron rehavi vian pasvorton.", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "noPermission": "Neniu permeso", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "Neniuj ĉambroj troviĝis…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "notifications": "Sciigoj", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "notificationsEnabledForThisAccount": "Sciigoj ŝaltiĝis por ĉi tiu konto", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "numUsersTyping": "{count} uzantoj tajpas…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "obtainingLocation": "Akirante lokon…", - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "offensive": "Ofenda", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "offline": "Eksterrete", - "@offline": { - "type": "text", - "placeholders": {} - }, - "ok": "bone", - "@ok": { - "type": "text", - "placeholders": {} - }, - "online": "Enrete", - "@online": { - "type": "text", - "placeholders": {} - }, - "onlineKeyBackupEnabled": "Enreta savkopiado de ŝlosiloj estas ŝaltita", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "oopsPushError": "Oj! Bedaŭrinde eraris la agordado de pasivaj sciigoj.", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "Oj! Io misokazis…", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "Malfermu la aplikaĵon por legi mesaĝojn", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "openCamera": "Malfermi fotilon", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "or": "Aŭ", - "@or": { - "type": "text", - "placeholders": {} - }, - "participant": "Partoprenanto", - "@participant": { - "type": "text", - "placeholders": {} - }, - "passphraseOrKey": "pasfrazo aŭ rehava ŝlosilo", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "password": "Pasvorto", - "@password": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "Forgesita pasvorto", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "Pasvorto ŝanĝiĝis", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "passwordRecovery": "Rehavo de pasvorto", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "people": "Personoj", - "@people": { - "type": "text", - "placeholders": {} - }, - "pickImage": "Elekti bildon", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "pin": "Fiksi", - "@pin": { - "type": "text", - "placeholders": {} - }, - "play": "Ludi {fileName}", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "pleaseChoose": "Bonvolu elekti", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "pleaseChooseAPasscode": "Bonvolu elekti paskodon", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pleaseClickOnLink": "Bonvolu klaki la ligilon en la retletero kaj pluiĝi.", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "Bonvolu enigi 4 ciferojn, aŭ nenion por malŝalti ŝlosadon de la aplikaĵo.", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "Bonvolu enigi vian pasvorton", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "Bonvolu enigi vian personan identigan numeron", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "Bonvolu enigi vian uzantonomon", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "pleaseFollowInstructionsOnWeb": "Bonvolu sekvi la instrukciojn de la retejo kaj tuŝetu al «Sekva».", - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "privacy": "Privateco", - "@privacy": { - "type": "text", - "placeholders": {} - }, - "publicRooms": "Publikaj ĉambroj", - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "pushRules": "Reguloj de pasivaj sciigoj", - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "reason": "Kialo", - "@reason": { - "type": "text", - "placeholders": {} - }, - "recording": "Registrante", - "@recording": { - "type": "text", - "placeholders": {} - }, - "redactedAnEvent": "{username} obskurigis eventon", - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "redactMessage": "Obskurigi mesaĝon", - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "register": "Registriĝi", - "@register": { - "type": "text", - "placeholders": {} - }, - "reject": "Rifuzi", - "@reject": { - "type": "text", - "placeholders": {} - }, - "rejectedTheInvitation": "{username} rifuzis la inviton", - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "rejoin": "Ree aliĝi", - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "remove": "Forigi", - "@remove": { - "type": "text", - "placeholders": {} - }, - "removeAllOtherDevices": "Forigi ĉiujn aliajn aparatojn", - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "removedBy": "Forigita de {username}", - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removeDevice": "Forigi aparaton", - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "unbanFromChat": "Malforbari", - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "removeYourAvatar": "Forigi vian profilbildon", - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "renderRichContent": "Bildigi riĉforman enhavon de mesaĝoj", - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "replaceRoomWithNewerVersion": "Anstataŭigi ĉambron per nova versio", - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "reply": "Respondi", - "@reply": { - "type": "text", - "placeholders": {} - }, - "reportMessage": "Raporti mesaĝon", - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "requestPermission": "Peti permeson", - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "roomHasBeenUpgraded": "Ĉambro gradaltiĝis", - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "roomVersion": "Versio de ĉambro", - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "saveFile": "Konservi dosieron", - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "search": "Serĉi", - "@search": { - "type": "text", - "placeholders": {} - }, - "security": "Sekureco", - "@security": { - "type": "text", - "placeholders": {} - }, - "seenByUser": "Vidita de {username}", - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "send": "Sendi", - "@send": { - "type": "text", - "placeholders": {} - }, - "sendAMessage": "Sendi mesaĝon", - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "sendAudio": "Sendi sondosieron", - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "sendFile": "Sendi dosieron", - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "sendImage": "Sendi bildon", - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "sendMessages": "Sendi mesaĝojn", - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "sendOriginal": "Sendi originalon", - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "sendSticker": "Sendi glumarkon", - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "sendVideo": "Sendi filmon", - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "sentAFile": "{username} sendis dosieron", - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAnAudio": "{username} sendis sondosieron", - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAPicture": "{username} sendis bildon", - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentASticker": "{username} sendis glumarkon", - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAVideo": "{username} sendis filmon", - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentCallInformations": "{senderName} sendis informojn pri voko", - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "setAsCanonicalAlias": "Agordi kiel ĉefan kromnomon", - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "setCustomEmotes": "Agordi proprajn mienetojn", - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "setInvitationLink": "Agordi invitan ligilon", - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "setPermissionsLevel": "Agordi nivelon de permesoj", - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "setStatus": "Agordi staton", - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "settings": "Agordoj", - "@settings": { - "type": "text", - "placeholders": {} - }, - "share": "Konigi", - "@share": { - "type": "text", - "placeholders": {} - }, - "sharedTheLocation": "{username} konigis sian lokon", - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "shareLocation": "Konigi lokon", - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "showPassword": "Montri pasvorton", - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "singlesignon": "Ununura saluto", - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "skip": "Preterpasi", - "@skip": { - "type": "text", - "placeholders": {} - }, - "sourceCode": "Fontkodo", - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "spaceIsPublic": "Aro estas publika", - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "spaceName": "Nomo de aro", - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "startedACall": "{senderName} komencis vokon", - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "status": "Stato", - "@status": { - "type": "text", - "placeholders": {} - }, - "statusExampleMessage": "Kiel vi fartas?", - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "submit": "Sendi", - "@submit": { - "type": "text", - "placeholders": {} - }, - "synchronizingPleaseWait": "Spegulante… Bonvolu atendi.", - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "systemTheme": "Sistema", - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "theyDontMatch": "Ili ne akordas", - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "theyMatch": "Ili akordas", - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "title": "FluffyChat", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "toggleFavorite": "Baskuli elstarigon", - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "toggleMuted": "Basklui silentigon", - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "toggleUnread": "Baskuli legitecon", - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "tooManyRequestsWarning": "Tro multaj petoj. Bonvolu reprovi poste!", - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "transferFromAnotherDevice": "Transporti de alia aparato", - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "tryToSendAgain": "Reprovi sendi", - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "unavailable": "Nedisponeble", - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "unbannedUser": "{username} malforbaris uzanton {targetName}", - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "unblockDevice": "Malbloki aparaton", - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "unknownDevice": "Nekonata aparato", - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "unknownEncryptionAlgorithm": "Nekonata ĉifra algoritmo", - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "unknownEvent": "Nekonata evento «{type}»", - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "unmuteChat": "Malsilentigi babilon", - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "unpin": "Malfiksi", - "@unpin": { - "type": "text", - "placeholders": {} - }, - "unreadChats": "{unreadCount, plural, =1{1 nelegita babilo} other{{unreadCount} nelegitaj babiloj}}", - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "userAndOthersAreTyping": "{username} kaj {count} aliaj tajpas…", - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "userAndUserAreTyping": "{username} kaj {username2} tajpas…", - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "userIsTyping": "{username} tajpas…", - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "userLeftTheChat": "{username} foriris de la babilo", - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "username": "Uzantonomo", - "@username": { - "type": "text", - "placeholders": {} - }, - "userSentUnknownEvent": "{username} sendis eventon de speco {type}", - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "verified": "Kontrolita", - "@verified": { - "type": "text", - "placeholders": {} - }, - "verify": "Kontroli", - "@verify": { - "type": "text", - "placeholders": {} - }, - "verifyStart": "Komenci kontrolon", - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "verifySuccess": "Vi sukcese kontrolis!", - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "verifyTitle": "Kontrolante alian konton", - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "videoCall": "Vidvoko", - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "visibilityOfTheChatHistory": "Videbleco de historio de la babilo", - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "visibleForAllParticipants": "Videbla al ĉiuj partoprenantoj", - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "visibleForEveryone": "Videbla al ĉiuj", - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "voiceMessage": "Voĉmesaĝo", - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerAcceptRequest": "Atendante konfirmon de peto de la kunulo…", - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerEmoji": "Atendante akcepton de la bildosignoj de la kunulo…", - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerNumbers": "Atendante akcepton de la numeroj, de la kunulo…", - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "wallpaper": "Fonbildo", - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "warning": "Averto!", - "@warning": { - "type": "text", - "placeholders": {} - }, - "weSentYouAnEmail": "Ni sendis retleteron al vi", - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "whoCanPerformWhichAction": "Kiu povas kion", - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "whoIsAllowedToJoinThisGroup": "Kiu rajtas aliĝi al ĉi tiu grupo", - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "whyDoYouWantToReportThis": "Kial vi volas tion ĉi raporti?", - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "wipeChatBackup": "Ĉu forviŝi la savkopion de via babilo por krei novan sekurecan ŝlosilon?", - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "withTheseAddressesRecoveryDescription": "Per tiuj ĉi adresoj vi povas rehavi vian pasvorton.", - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "writeAMessage": "Skribi mesaĝon…", - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "yes": "Jes", - "@yes": { - "type": "text", - "placeholders": {} - }, - "you": "Vi", - "@you": { - "type": "text", - "placeholders": {} - }, - "youAreNoLongerParticipatingInThisChat": "Vi ne plu partoprenas ĉi tiun babilon", - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "youHaveBeenBannedFromThisChat": "Vi estas forbarita de ĉi tiu babilo", - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "yourPublicKey": "Via publika ŝlosilo", - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "sendAsText": "Sendi kiel tekston", - "@sendAsText": { - "type": "text" - }, - "noMatrixServer": "{server1} ne estas matriksa servilo, eble provu anstataŭe servilon {server2}?", - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "commandHint_send": "Sendi tekston", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "chatHasBeenAddedToThisSpace": "Babilo aldoniĝis al ĉi tiu aro", - "@chatHasBeenAddedToThisSpace": {}, - "autoplayImages": "Memage ludi movbildajn glumarkojn kaj mienetojn", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "addToSpace": "Aldoni al aro", - "@addToSpace": {}, - "homeserver": "Hejmservilo", - "@homeserver": {}, - "sendOnEnter": "Sendi per eniga klavo", - "@sendOnEnter": {}, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@widgetVideo": {}, - "@dismiss": {}, - "@reportErrorDescription": {}, - "@addAccount": {}, - "@unsupportedAndroidVersion": {}, - "@widgetJitsi": {}, - "@messageType": {}, - "@indexedDbErrorLong": {}, - "@oneClientLoggedOut": {}, - "@startFirstChat": {}, - "@callingAccount": {}, - "@setColorTheme": {}, - "@nextAccount": {}, - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "@allSpaces": {}, - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "@user": {}, - "@youAcceptedTheInvitation": {}, - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "@banUserDescription": {}, - "@widgetEtherpad": {}, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "@unbanUserDescription": {}, - "@youRejectedTheInvitation": {}, - "@otherCallingPermissions": {}, - "@messagesStyle": {}, - "@link": {}, - "@widgetUrlError": {}, - "@emailOrUsername": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@enterSpace": {}, - "@encryptThisChat": {}, - "@previousAccount": {}, - "@reopenChat": {}, - "@pleaseEnterRecoveryKey": {}, - "@widgetNameError": {}, - "@addToBundle": {}, - "@addWidget": {}, - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "@noKeyForThisMessage": {}, - "@commandHint_markasgroup": {}, - "@hydrateTor": {}, - "@pushNotificationsNotAvailable": {}, - "@storeInAppleKeyChain": {}, - "@hydrate": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@sender": {}, - "@storeInAndroidKeystore": {}, - "@signInWithPassword": {}, - "@makeAdminDescription": {}, - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "@saveKeyManuallyDescription": {}, - "@editBundlesForAccount": {}, - "@whyIsThisMessageEncrypted": {}, - "@setChatDescription": {}, - "@importFromZipFile": {}, - "@dehydrateWarning": {}, - "@noOtherDevicesFound": {}, - "@yourChatBackupHasBeenSetUp": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@videoCallsBetaWarning": {}, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@fileIsTooBigForServer": {}, - "@repeatPassword": {}, - "@callingPermissions": {}, - "@readUpToHere": {}, - "@start": {}, - "@unlockOldMessages": {}, - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@optionalRedactReason": {}, - "@dehydrate": {}, - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "@experimentalVideoCalls": {}, - "@pleaseEnterRecoveryKeyDescription": {}, - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "@appearOnTopDetails": {}, - "@enterRoom": {}, - "@reportUser": {}, - "@confirmEventUnpin": {}, - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@redactMessageDescription": {}, - "@recoveryKey": {}, - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "@invalidInput": {}, - "@dehydrateTorLong": {}, - "@doNotShowAgain": {}, - "@report": {}, - "@unverified": {}, - "@serverRequiresEmail": {}, - "@hideUnimportantStateEvents": {}, - "@screenSharingTitle": {}, - "@widgetCustom": {}, - "@addToSpaceDescription": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "@addChatDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@publish": {}, - "@openLinkInBrowser": {}, - "@messageInfo": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@foregroundServiceRunning": {}, - "@voiceCall": {}, - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "@noChatDescriptionYet": {}, - "@removeFromBundle": {}, - "@confirmMatrixId": {}, - "@learnMore": {}, - "@notAnImage": {}, - "@users": {}, - "@openGallery": {}, - "@chatDescriptionHasBeenChanged": {}, - "@newGroup": {}, - "@bundleName": {}, - "@dehydrateTor": {}, - "@removeFromSpace": {}, - "@roomUpgradeDescription": {}, - "@scanQrCode": {}, - "@pleaseEnterANumber": {}, - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "@profileNotFound": {}, - "@jump": {}, - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "@sorryThatsNotPossible": {}, - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "@shareInviteLink": {}, - "@commandHint_markasdm": {}, - "@recoveryKeyLost": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@deviceKeys": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@youJoinedTheChat": {}, - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "@markAsRead": {}, - "@widgetName": {}, - "@errorAddingWidget": {}, - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "@commandHint_hug": {}, - "@replace": {}, - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "@newSpace": {}, - "@emojis": {}, - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@hydrateTorLong": {}, - "@time": {}, - "@custom": {}, - "@noBackupWarning": {}, - "@storeInSecureStorageDescription": {}, - "@openChat": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@pinMessage": {}, - "@invite": {}, - "@enableMultiAccounts": {}, - "@indexedDbErrorTitle": {}, - "@unsupportedAndroidVersionLong": {}, - "@storeSecurlyOnThisDevice": {}, - "@screenSharingDetail": {}, - "@placeCall": {} -} \ No newline at end of file + "@@last_modified": "2021-08-14 12:41:10.107750", + "about": "Prio", + "@about": { + "type": "text", + "placeholders": {} + }, + "accept": "Akcepti", + "@accept": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "{username} akceptis la inviton", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "account": "Konto", + "@account": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "{username} aktivigis tutvojan ĉifradon", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "addEmail": "Aldoni retpoŝtadreson", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "admin": "Administranto", + "@admin": { + "type": "text", + "placeholders": {} + }, + "alias": "kromnomo", + "@alias": { + "type": "text", + "placeholders": {} + }, + "all": "Ĉio", + "@all": { + "type": "text", + "placeholders": {} + }, + "allChats": "Ĉiuj babiloj", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "{senderName} respondis la vokon", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "anyoneCanJoin": "Ĉiu ajn povas aliĝi", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "appLock": "Ŝlosado", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "archive": "Arĥivo", + "@archive": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "Ĉu gastoj rajtas aliĝi", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "Ĉu vi certas?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "areYouSureYouWantToLogout": "Ĉu vi certe volas adiaŭi?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "askSSSSSign": "Por ke vi povu kontroli (subskribi) la alian personon, bonvolu enigi pasfrazon de via sekreta deponejo aŭ vian rehavan ŝlosilon.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "Ĉu akcepti ĉi tiun kontrolpeton de {username}?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "badServerLoginTypesException": "La hejmservilo subtenas la jenajn specojn de salutoj:\n{serverVersions}\nSed ĉi tiu aplikaĵo subtenas nur:\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "badServerVersionsException": "La hejmservilo subtenas la jenajn version de la specifaĵo:\n{serverVersions}\nSed ĉi tiu aplikaĵo subtenas nur {supportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "banFromChat": "Forbari de babilo", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "banned": "Forbarita", + "@banned": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "{username} forbaris uzanton {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "blockDevice": "Bloki aparaton", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "blocked": "Blokita", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "botMessages": "Mesaĝoj de robotoj", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "cancel": "Nuligi", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "cantOpenUri": "Ne povis malfermi URI {uri}", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "changeDeviceName": "Ŝanĝi nomon de aparato", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "changedTheChatAvatar": "{username} ŝanĝis bildon de la babilo", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatDescriptionTo": "{username} ŝanĝis priskribon de la babilo al: «{description}»", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "changedTheChatNameTo": "{username} ŝanĝis nomon de la babilo al: «{chatname}»", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changedTheChatPermissions": "{username} ŝanĝis permesojn pri la babilo", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "{username} ŝanĝis sian prezentan nomon al: {username}", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRules": "{username} ŝanĝis regulojn pri aliro de gastoj", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheGuestAccessRulesTo": "{username} ŝanĝis regulojn pri aliro de gastoj al: {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheHistoryVisibility": "{username} ŝanĝis videblecon de la historio", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibilityTo": "{username} ŝanĝis videblecon de la historio al: {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRules": "{username} ŝanĝis regulojn pri aliĝado", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheJoinRulesTo": "{username} ŝanĝis regulojn pri aliĝado al: {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheProfileAvatar": "{username} ŝanĝis sian profilbildon", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "{username} ŝanĝis la kromnomojn de la ĉambro", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomInvitationLink": "{username} ŝanĝis la invitan ligilon", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changePassword": "Ŝanĝi pasvorton", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "changeTheHomeserver": "Ŝanĝi hejmservilon", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "Ŝanĝu la haŭton", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "Ŝanĝi nomon de la grupo", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "changeYourAvatar": "Ŝanĝi vian profilbildon", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "channelCorruptedDecryptError": "La ĉifrado estas difektita", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "chat": "Babilo", + "@chat": { + "type": "text", + "placeholders": {} + }, + "chatBackup": "Savkopiado de babilo", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "chatBackupDescription": "Via savkopio de babilo estas sekurigita per sekureca ŝlosilo. Bonvolu certigi, ke vi ne perdos ĝin.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "chatDetails": "Detaloj pri babilo", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chats": "Babiloj", + "@chats": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "Elektu fortan pasvorton", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "clearArchive": "Vakigi arĥivon", + "@clearArchive": {}, + "close": "Fermi", + "@close": { + "type": "text", + "placeholders": {} + }, + "commandHint_ban": "Forbari la donitan uzanton de ĉi tiu ĉambro", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_html": "Sendi tekston formatan je HTML", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_invite": "Inviti la donitan uzanton al ĉi tiu ĉambro", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "commandHint_join": "Aliĝi al la donita ĉambro", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_kick": "Forigi la donitan uzanton de ĉi tiu ĉambro", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_leave": "Foriri de ĉi tiu ĉambro", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_me": "Priskribu vian agon", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "commandHint_myroomavatar": "Agordi vian profilbildon por ĉi tiu ĉambro (laŭ mxc-uri)", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_myroomnick": "Agordi vian prezentan nomon en ĉi tiu ĉambro", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "commandHint_op": "Agordi povnivelon de la donita uzanto (implicite: 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_plain": "Sendi senformatan tekston", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_react": "Sendi respondon kiel reagon", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "commandHint_unban": "Malforbari la donitan uzanton de ĉi tiu ĉambro", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "commandInvalid": "Nevalida ordono", + "@commandInvalid": { + "type": "text" + }, + "commandMissing": "{command} ne estas ordono.", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "compareEmojiMatch": "Komparu kaj certigu, ke la jenaj bildosignoj samas en ambaŭ aparatoj:", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "Komparu kaj certigu, ke la jenaj numeroj samas en ambaŭ aparatoj:", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "configureChat": "Agordi babilon", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "confirm": "Konfirmi", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "connect": "Konektiĝi", + "@connect": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "Kontakto invitiĝis al la grupo", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "Enhavas prezentan nomon", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "containsUserName": "Enhavas uzantonomon", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "La enhavo raportiĝis al la administrantoj de la servilo", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "Kopiite al tondujo", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "copy": "Kopii", + "@copy": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "Kopii al tondujo", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "Ne povis malĉifri mesaĝon: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "countParticipants": "{count} partoprenantoj", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "create": "Krei", + "@create": { + "type": "text", + "placeholders": {} + }, + "createdTheChat": "{username} kreis la babilon", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "createNewSpace": "Nova aro", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "currentlyActive": "Nun aktiva", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "Malhela", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "dateWithoutYear": "{day}a de la {month}a", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "dateWithYear": "{day}a de la {month}a de {year}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "deactivateAccountWarning": "Ĉi tio malaktivigos vian konton de uzanto. Ne eblas tion malfari! Ĉu certe vi certas?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "Norma nivelo de permesoj", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "delete": "Forigi", + "@delete": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "Forigi konton", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "Forigi mesaĝon", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "device": "Aparato", + "@device": { + "type": "text", + "placeholders": {} + }, + "deviceId": "Identigilo de aparato", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "devices": "Aparatoj", + "@devices": { + "type": "text", + "placeholders": {} + }, + "directChats": "Rektaj babiloj", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "displaynameHasBeenChanged": "Prezenta nomo ŝanĝiĝis", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "Elŝuti dosieron", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "edit": "Redakti", + "@edit": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "Redakti blokitajn servilojn", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "Redakti prezentan nomon", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "Ŝanĝi kromnomojn de ĉambro", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "Redakti bildon de ĉambro", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "Mieneto jam ekzistas!", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "emoteInvalid": "Nevalida mallongigo de mieneto!", + "@emoteInvalid": { + "type": "text", + "placeholders": {} + }, + "emotePacks": "Mienetaroj por la ĉambro", + "@emotePacks": { + "type": "text", + "placeholders": {} + }, + "emoteSettings": "Agordoj pri mienetoj", + "@emoteSettings": { + "type": "text", + "placeholders": {} + }, + "emoteShortcode": "Mallongigo de mieneto", + "@emoteShortcode": { + "type": "text", + "placeholders": {} + }, + "emoteWarnNeedToPick": "Vi devas elekti mallongigon de mieneto kaj bildon!", + "@emoteWarnNeedToPick": { + "type": "text", + "placeholders": {} + }, + "emptyChat": "Malplena babilo", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "enableEmotesGlobally": "Ŝalti mienetaron ĉie", + "@enableEmotesGlobally": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "Ŝalti ĉifradon", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "enableEncryptionWarning": "Vi ne povos malŝalti la ĉifradon. Ĉu vi certas?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "encrypted": "Ĉifrite", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "encryption": "Ĉifrado", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "encryptionNotEnabled": "Ĉifrado ne estas ŝaltita", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "{senderName} finis la vokon", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "enterAnEmailAddress": "Enigu retpoŝtadreson", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "enterYourHomeserver": "Enigu vian hejmservilon", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "errorObtainingLocation": "Eraris akirado de loko: {error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "everythingReady": "Ĉio pretas!", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "extremeOffensive": "Tre ofenda", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "fileName": "Dosiernomo", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "fontSize": "Grandeco de tiparo", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "forward": "Plusendi", + "@forward": { + "type": "text", + "placeholders": {} + }, + "fromJoining": "Ekde aliĝo", + "@fromJoining": { + "type": "text", + "placeholders": {} + }, + "fromTheInvitation": "Ekde la invito", + "@fromTheInvitation": { + "type": "text", + "placeholders": {} + }, + "goToTheNewRoom": "Iri al la nova ĉambro", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "group": "Grupo", + "@group": { + "type": "text", + "placeholders": {} + }, + "groupIsPublic": "Grupo estas publika", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "groups": "Grupoj", + "@groups": { + "type": "text", + "placeholders": {} + }, + "groupWith": "Grupo kun {displayname}", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "guestsAreForbidden": "Gastoj estas malpermesitaj", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "Gastoj povas aliĝi", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "hasWithdrawnTheInvitationFor": "{username} nuligis la inviton por {targetName}", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "help": "Helpo", + "@help": { + "type": "text", + "placeholders": {} + }, + "hideRedactedEvents": "Kaŝi obskurigitajn eventojn", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "Kaŝi nekonatajn eventojn", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "howOffensiveIsThisContent": "Kiel ofenda estas ĉi tiu enhavo?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "id": "Identigilo", + "@id": { + "type": "text", + "placeholders": {} + }, + "identity": "Identeco", + "@identity": { + "type": "text", + "placeholders": {} + }, + "ignore": "Malatenti", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "Malatentitaj uzantoj", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "Mi klakis la ligilon", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "incorrectPassphraseOrKey": "Neĝusta pasfrazo aŭ rehava ŝlosilo", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "Neofenda", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "Inviti kontakton", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "Inviti kontakton al {groupName}", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "invited": "Invitita", + "@invited": { + "type": "text", + "placeholders": {} + }, + "invitedUser": "{username} invitis uzanton {targetName}", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "invitedUsersOnly": "Nur invititoj", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "inviteForMe": "Invito por mi", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "inviteText": "{username} invitis vin al FluffyChat. \n1. Instalu la aplikaĵon FluffyChat: https://fluffychat.im \n2. Registriĝu aŭ salutu \n3. Malfermu la invitan ligilon: {link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "isTyping": "tajpas…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "joinedTheChat": "{username} aliĝis al la babilo", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "joinRoom": "Aliĝi al ĉambro", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "kicked": "{username} forpelis uzanton {targetName}", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickedAndBanned": "{username} forpelis kaj forbaris uzanton {targetName}", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickFromChat": "Forpeli de babilo", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "lastActiveAgo": "Lastafoje aktiva: {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "leave": "Foriri", + "@leave": { + "type": "text", + "placeholders": {} + }, + "leftTheChat": "Foriris de la ĉambro", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "license": "Permesilo", + "@license": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "Hela", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "loadCountMoreParticipants": "Enlegi {count} pliajn partoprenantojn", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "loadingPleaseWait": "Enlegante… bonvolu atendi.", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "loadMore": "Enlegi pli…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "login": "Saluti", + "@login": { + "type": "text", + "placeholders": {} + }, + "logInTo": "Saluti servilon {homeserver}", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "logout": "Adiaŭi", + "@logout": { + "type": "text", + "placeholders": {} + }, + "memberChanges": "Ŝanĝoj de anoj", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "mention": "Mencii", + "@mention": { + "type": "text", + "placeholders": {} + }, + "messages": "Mesaĝoj", + "@messages": { + "type": "text", + "placeholders": {} + }, + "moderator": "Reguligisto", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "muteChat": "Silentigi babilon", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "Bonvolu scii, ke vi ankoraŭ bezonas la programon Pantalaimon por uzi tutvojan ĉifradon.", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "newChat": "Nova babilo", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "Nova mesaĝo en FluffyChat", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "newVerificationRequest": "Nova kontrolpeto!", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "next": "Sekva", + "@next": { + "type": "text", + "placeholders": {} + }, + "no": "Ne", + "@no": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "Neniu konekto al la servilo", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "noEmotesFound": "Neniuj mienetoj troviĝis. 😕", + "@noEmotesFound": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "Vi nur povas aktivigi ĉifradon kiam la ĉambro ne plu estas publike alirebla.", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "noGoogleServicesWarning": "Ŝajnas, ke via telefono ne havas servojn de Google. Tio estas bona decido por via privateco! Por ricevadi pasivajn sciigojn en FluffyChat, ni rekomendas, ke vi uzu la https://microg.org/ aŭ https://unifiedpush.org/.", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "none": "Neniu", + "@none": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "Vi ankoraŭ ne aldonis manieron rehavi vian pasvorton.", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "noPermission": "Neniu permeso", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "Neniuj ĉambroj troviĝis…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "notifications": "Sciigoj", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "notificationsEnabledForThisAccount": "Sciigoj ŝaltiĝis por ĉi tiu konto", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "numUsersTyping": "{count} uzantoj tajpas…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "obtainingLocation": "Akirante lokon…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "offensive": "Ofenda", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "offline": "Eksterrete", + "@offline": { + "type": "text", + "placeholders": {} + }, + "ok": "bone", + "@ok": { + "type": "text", + "placeholders": {} + }, + "online": "Enrete", + "@online": { + "type": "text", + "placeholders": {} + }, + "onlineKeyBackupEnabled": "Enreta savkopiado de ŝlosiloj estas ŝaltita", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "Oj! Bedaŭrinde eraris la agordado de pasivaj sciigoj.", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "Oj! Io misokazis…", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "Malfermu la aplikaĵon por legi mesaĝojn", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "openCamera": "Malfermi fotilon", + "@openCamera": { + "type": "text", + "placeholders": {} + }, + "or": "Aŭ", + "@or": { + "type": "text", + "placeholders": {} + }, + "participant": "Partoprenanto", + "@participant": { + "type": "text", + "placeholders": {} + }, + "passphraseOrKey": "pasfrazo aŭ rehava ŝlosilo", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "password": "Pasvorto", + "@password": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "Forgesita pasvorto", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "Pasvorto ŝanĝiĝis", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "passwordRecovery": "Rehavo de pasvorto", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "people": "Personoj", + "@people": { + "type": "text", + "placeholders": {} + }, + "pickImage": "Elekti bildon", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "pin": "Fiksi", + "@pin": { + "type": "text", + "placeholders": {} + }, + "play": "Ludi {fileName}", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "pleaseChoose": "Bonvolu elekti", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "pleaseChooseAPasscode": "Bonvolu elekti paskodon", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pleaseClickOnLink": "Bonvolu klaki la ligilon en la retletero kaj pluiĝi.", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "Bonvolu enigi 4 ciferojn, aŭ nenion por malŝalti ŝlosadon de la aplikaĵo.", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "Bonvolu enigi vian pasvorton", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "Bonvolu enigi vian personan identigan numeron", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "Bonvolu enigi vian uzantonomon", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "pleaseFollowInstructionsOnWeb": "Bonvolu sekvi la instrukciojn de la retejo kaj tuŝetu al «Sekva».", + "@pleaseFollowInstructionsOnWeb": { + "type": "text", + "placeholders": {} + }, + "privacy": "Privateco", + "@privacy": { + "type": "text", + "placeholders": {} + }, + "publicRooms": "Publikaj ĉambroj", + "@publicRooms": { + "type": "text", + "placeholders": {} + }, + "pushRules": "Reguloj de pasivaj sciigoj", + "@pushRules": { + "type": "text", + "placeholders": {} + }, + "reason": "Kialo", + "@reason": { + "type": "text", + "placeholders": {} + }, + "recording": "Registrante", + "@recording": { + "type": "text", + "placeholders": {} + }, + "redactedAnEvent": "{username} obskurigis eventon", + "@redactedAnEvent": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "redactMessage": "Obskurigi mesaĝon", + "@redactMessage": { + "type": "text", + "placeholders": {} + }, + "register": "Registriĝi", + "@register": { + "type": "text", + "placeholders": {} + }, + "reject": "Rifuzi", + "@reject": { + "type": "text", + "placeholders": {} + }, + "rejectedTheInvitation": "{username} rifuzis la inviton", + "@rejectedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "rejoin": "Ree aliĝi", + "@rejoin": { + "type": "text", + "placeholders": {} + }, + "remove": "Forigi", + "@remove": { + "type": "text", + "placeholders": {} + }, + "removeAllOtherDevices": "Forigi ĉiujn aliajn aparatojn", + "@removeAllOtherDevices": { + "type": "text", + "placeholders": {} + }, + "removedBy": "Forigita de {username}", + "@removedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removeDevice": "Forigi aparaton", + "@removeDevice": { + "type": "text", + "placeholders": {} + }, + "unbanFromChat": "Malforbari", + "@unbanFromChat": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "Forigi vian profilbildon", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "renderRichContent": "Bildigi riĉforman enhavon de mesaĝoj", + "@renderRichContent": { + "type": "text", + "placeholders": {} + }, + "replaceRoomWithNewerVersion": "Anstataŭigi ĉambron per nova versio", + "@replaceRoomWithNewerVersion": { + "type": "text", + "placeholders": {} + }, + "reply": "Respondi", + "@reply": { + "type": "text", + "placeholders": {} + }, + "reportMessage": "Raporti mesaĝon", + "@reportMessage": { + "type": "text", + "placeholders": {} + }, + "requestPermission": "Peti permeson", + "@requestPermission": { + "type": "text", + "placeholders": {} + }, + "roomHasBeenUpgraded": "Ĉambro gradaltiĝis", + "@roomHasBeenUpgraded": { + "type": "text", + "placeholders": {} + }, + "roomVersion": "Versio de ĉambro", + "@roomVersion": { + "type": "text", + "placeholders": {} + }, + "saveFile": "Konservi dosieron", + "@saveFile": { + "type": "text", + "placeholders": {} + }, + "search": "Serĉi", + "@search": { + "type": "text", + "placeholders": {} + }, + "security": "Sekureco", + "@security": { + "type": "text", + "placeholders": {} + }, + "seenByUser": "Vidita de {username}", + "@seenByUser": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "send": "Sendi", + "@send": { + "type": "text", + "placeholders": {} + }, + "sendAMessage": "Sendi mesaĝon", + "@sendAMessage": { + "type": "text", + "placeholders": {} + }, + "sendAudio": "Sendi sondosieron", + "@sendAudio": { + "type": "text", + "placeholders": {} + }, + "sendFile": "Sendi dosieron", + "@sendFile": { + "type": "text", + "placeholders": {} + }, + "sendImage": "Sendi bildon", + "@sendImage": { + "type": "text", + "placeholders": {} + }, + "sendMessages": "Sendi mesaĝojn", + "@sendMessages": { + "type": "text", + "placeholders": {} + }, + "sendOriginal": "Sendi originalon", + "@sendOriginal": { + "type": "text", + "placeholders": {} + }, + "sendSticker": "Sendi glumarkon", + "@sendSticker": { + "type": "text", + "placeholders": {} + }, + "sendVideo": "Sendi filmon", + "@sendVideo": { + "type": "text", + "placeholders": {} + }, + "sentAFile": "{username} sendis dosieron", + "@sentAFile": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAnAudio": "{username} sendis sondosieron", + "@sentAnAudio": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAPicture": "{username} sendis bildon", + "@sentAPicture": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentASticker": "{username} sendis glumarkon", + "@sentASticker": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAVideo": "{username} sendis filmon", + "@sentAVideo": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentCallInformations": "{senderName} sendis informojn pri voko", + "@sentCallInformations": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "setAsCanonicalAlias": "Agordi kiel ĉefan kromnomon", + "@setAsCanonicalAlias": { + "type": "text", + "placeholders": {} + }, + "setCustomEmotes": "Agordi proprajn mienetojn", + "@setCustomEmotes": { + "type": "text", + "placeholders": {} + }, + "setInvitationLink": "Agordi invitan ligilon", + "@setInvitationLink": { + "type": "text", + "placeholders": {} + }, + "setPermissionsLevel": "Agordi nivelon de permesoj", + "@setPermissionsLevel": { + "type": "text", + "placeholders": {} + }, + "setStatus": "Agordi staton", + "@setStatus": { + "type": "text", + "placeholders": {} + }, + "settings": "Agordoj", + "@settings": { + "type": "text", + "placeholders": {} + }, + "share": "Konigi", + "@share": { + "type": "text", + "placeholders": {} + }, + "sharedTheLocation": "{username} konigis sian lokon", + "@sharedTheLocation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "shareLocation": "Konigi lokon", + "@shareLocation": { + "type": "text", + "placeholders": {} + }, + "showPassword": "Montri pasvorton", + "@showPassword": { + "type": "text", + "placeholders": {} + }, + "singlesignon": "Ununura saluto", + "@singlesignon": { + "type": "text", + "placeholders": {} + }, + "skip": "Preterpasi", + "@skip": { + "type": "text", + "placeholders": {} + }, + "sourceCode": "Fontkodo", + "@sourceCode": { + "type": "text", + "placeholders": {} + }, + "spaceIsPublic": "Aro estas publika", + "@spaceIsPublic": { + "type": "text", + "placeholders": {} + }, + "spaceName": "Nomo de aro", + "@spaceName": { + "type": "text", + "placeholders": {} + }, + "startedACall": "{senderName} komencis vokon", + "@startedACall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "status": "Stato", + "@status": { + "type": "text", + "placeholders": {} + }, + "statusExampleMessage": "Kiel vi fartas?", + "@statusExampleMessage": { + "type": "text", + "placeholders": {} + }, + "submit": "Sendi", + "@submit": { + "type": "text", + "placeholders": {} + }, + "synchronizingPleaseWait": "Spegulante… Bonvolu atendi.", + "@synchronizingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "systemTheme": "Sistema", + "@systemTheme": { + "type": "text", + "placeholders": {} + }, + "theyDontMatch": "Ili ne akordas", + "@theyDontMatch": { + "type": "text", + "placeholders": {} + }, + "theyMatch": "Ili akordas", + "@theyMatch": { + "type": "text", + "placeholders": {} + }, + "title": "FluffyChat", + "@title": { + "description": "Title for the application", + "type": "text", + "placeholders": {} + }, + "toggleFavorite": "Baskuli elstarigon", + "@toggleFavorite": { + "type": "text", + "placeholders": {} + }, + "toggleMuted": "Basklui silentigon", + "@toggleMuted": { + "type": "text", + "placeholders": {} + }, + "toggleUnread": "Baskuli legitecon", + "@toggleUnread": { + "type": "text", + "placeholders": {} + }, + "tooManyRequestsWarning": "Tro multaj petoj. Bonvolu reprovi poste!", + "@tooManyRequestsWarning": { + "type": "text", + "placeholders": {} + }, + "transferFromAnotherDevice": "Transporti de alia aparato", + "@transferFromAnotherDevice": { + "type": "text", + "placeholders": {} + }, + "tryToSendAgain": "Reprovi sendi", + "@tryToSendAgain": { + "type": "text", + "placeholders": {} + }, + "unavailable": "Nedisponeble", + "@unavailable": { + "type": "text", + "placeholders": {} + }, + "unbannedUser": "{username} malforbaris uzanton {targetName}", + "@unbannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "unblockDevice": "Malbloki aparaton", + "@unblockDevice": { + "type": "text", + "placeholders": {} + }, + "unknownDevice": "Nekonata aparato", + "@unknownDevice": { + "type": "text", + "placeholders": {} + }, + "unknownEncryptionAlgorithm": "Nekonata ĉifra algoritmo", + "@unknownEncryptionAlgorithm": { + "type": "text", + "placeholders": {} + }, + "unknownEvent": "Nekonata evento «{type}»", + "@unknownEvent": { + "type": "text", + "placeholders": { + "type": {} + } + }, + "unmuteChat": "Malsilentigi babilon", + "@unmuteChat": { + "type": "text", + "placeholders": {} + }, + "unpin": "Malfiksi", + "@unpin": { + "type": "text", + "placeholders": {} + }, + "unreadChats": "{unreadCount, plural, =1{1 nelegita babilo} other{{unreadCount} nelegitaj babiloj}}", + "@unreadChats": { + "type": "text", + "placeholders": { + "unreadCount": {} + } + }, + "userAndOthersAreTyping": "{username} kaj {count} aliaj tajpas…", + "@userAndOthersAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "count": {} + } + }, + "userAndUserAreTyping": "{username} kaj {username2} tajpas…", + "@userAndUserAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "username2": {} + } + }, + "userIsTyping": "{username} tajpas…", + "@userIsTyping": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "userLeftTheChat": "{username} foriris de la babilo", + "@userLeftTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "username": "Uzantonomo", + "@username": { + "type": "text", + "placeholders": {} + }, + "userSentUnknownEvent": "{username} sendis eventon de speco {type}", + "@userSentUnknownEvent": { + "type": "text", + "placeholders": { + "username": {}, + "type": {} + } + }, + "verified": "Kontrolita", + "@verified": { + "type": "text", + "placeholders": {} + }, + "verify": "Kontroli", + "@verify": { + "type": "text", + "placeholders": {} + }, + "verifyStart": "Komenci kontrolon", + "@verifyStart": { + "type": "text", + "placeholders": {} + }, + "verifySuccess": "Vi sukcese kontrolis!", + "@verifySuccess": { + "type": "text", + "placeholders": {} + }, + "verifyTitle": "Kontrolante alian konton", + "@verifyTitle": { + "type": "text", + "placeholders": {} + }, + "videoCall": "Vidvoko", + "@videoCall": { + "type": "text", + "placeholders": {} + }, + "visibilityOfTheChatHistory": "Videbleco de historio de la babilo", + "@visibilityOfTheChatHistory": { + "type": "text", + "placeholders": {} + }, + "visibleForAllParticipants": "Videbla al ĉiuj partoprenantoj", + "@visibleForAllParticipants": { + "type": "text", + "placeholders": {} + }, + "visibleForEveryone": "Videbla al ĉiuj", + "@visibleForEveryone": { + "type": "text", + "placeholders": {} + }, + "voiceMessage": "Voĉmesaĝo", + "@voiceMessage": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerAcceptRequest": "Atendante konfirmon de peto de la kunulo…", + "@waitingPartnerAcceptRequest": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerEmoji": "Atendante akcepton de la bildosignoj de la kunulo…", + "@waitingPartnerEmoji": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerNumbers": "Atendante akcepton de la numeroj, de la kunulo…", + "@waitingPartnerNumbers": { + "type": "text", + "placeholders": {} + }, + "wallpaper": "Fonbildo", + "@wallpaper": { + "type": "text", + "placeholders": {} + }, + "warning": "Averto!", + "@warning": { + "type": "text", + "placeholders": {} + }, + "weSentYouAnEmail": "Ni sendis retleteron al vi", + "@weSentYouAnEmail": { + "type": "text", + "placeholders": {} + }, + "whoCanPerformWhichAction": "Kiu povas kion", + "@whoCanPerformWhichAction": { + "type": "text", + "placeholders": {} + }, + "whoIsAllowedToJoinThisGroup": "Kiu rajtas aliĝi al ĉi tiu grupo", + "@whoIsAllowedToJoinThisGroup": { + "type": "text", + "placeholders": {} + }, + "whyDoYouWantToReportThis": "Kial vi volas tion ĉi raporti?", + "@whyDoYouWantToReportThis": { + "type": "text", + "placeholders": {} + }, + "wipeChatBackup": "Ĉu forviŝi la savkopion de via babilo por krei novan sekurecan ŝlosilon?", + "@wipeChatBackup": { + "type": "text", + "placeholders": {} + }, + "withTheseAddressesRecoveryDescription": "Per tiuj ĉi adresoj vi povas rehavi vian pasvorton.", + "@withTheseAddressesRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "writeAMessage": "Skribi mesaĝon…", + "@writeAMessage": { + "type": "text", + "placeholders": {} + }, + "yes": "Jes", + "@yes": { + "type": "text", + "placeholders": {} + }, + "you": "Vi", + "@you": { + "type": "text", + "placeholders": {} + }, + "youAreNoLongerParticipatingInThisChat": "Vi ne plu partoprenas ĉi tiun babilon", + "@youAreNoLongerParticipatingInThisChat": { + "type": "text", + "placeholders": {} + }, + "youHaveBeenBannedFromThisChat": "Vi estas forbarita de ĉi tiu babilo", + "@youHaveBeenBannedFromThisChat": { + "type": "text", + "placeholders": {} + }, + "yourPublicKey": "Via publika ŝlosilo", + "@yourPublicKey": { + "type": "text", + "placeholders": {} + }, + "sendAsText": "Sendi kiel tekston", + "@sendAsText": { + "type": "text" + }, + "noMatrixServer": "{server1} ne estas matriksa servilo, eble provu anstataŭe servilon {server2}?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "commandHint_send": "Sendi tekston", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "chatHasBeenAddedToThisSpace": "Babilo aldoniĝis al ĉi tiu aro", + "@chatHasBeenAddedToThisSpace": {}, + "autoplayImages": "Memage ludi movbildajn glumarkojn kaj mienetojn", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "addToSpace": "Aldoni al aro", + "@addToSpace": {}, + "homeserver": "Hejmservilo", + "@homeserver": {}, + "sendOnEnter": "Sendi per eniga klavo", + "@sendOnEnter": {} +} diff --git a/assets/l10n/intl_es.arb b/assets/l10n/intl_es.arb index 684a418e3..fb9c91df6 100644 --- a/assets/l10n/intl_es.arb +++ b/assets/l10n/intl_es.arb @@ -87,12 +87,12 @@ "type": "text", "placeholders": {} }, - "areYouSure": "¿Está seguro?", + "areYouSure": "¿Estás seguro?", "@areYouSure": { "type": "text", "placeholders": {} }, - "areYouSureYouWantToLogout": "¿Está seguro que quiere cerrar sesión?", + "areYouSureYouWantToLogout": "¿Confirma que quiere cerrar sesión?", "@areYouSureYouWantToLogout": { "type": "text", "placeholders": {} @@ -112,7 +112,7 @@ "type": "text", "placeholders": {} }, - "askVerificationRequest": "¿Acepta esta solicitud de verificación de {username}?", + "askVerificationRequest": "¿Aceptar esta solicitud de verificación de {username}?", "@askVerificationRequest": { "type": "text", "placeholders": { @@ -278,7 +278,7 @@ "username": {} } }, - "changedTheRoomAliases": "{username} cambió el alias del chat", + "changedTheRoomAliases": "{username} cambió el alias de la sala", "@changedTheRoomAliases": { "type": "text", "placeholders": { @@ -357,7 +357,7 @@ "type": "text", "placeholders": {} }, - "chats": "Chats de Groupos", + "chats": "Conversaciones", "@chats": { "type": "text", "placeholders": {} @@ -379,12 +379,12 @@ "type": "text", "placeholders": {} }, - "compareEmojiMatch": "Compare y asegúrese de que los siguientes emoji coincidan con los del otro dispositivo:", + "compareEmojiMatch": "Por favor compare los emojis", "@compareEmojiMatch": { "type": "text", "placeholders": {} }, - "compareNumbersMatch": "Compare y asegúrese de que los siguientes números coincidan con los del otro dispositivo:", + "compareNumbersMatch": "Por favor compare los números", "@compareNumbersMatch": { "type": "text", "placeholders": {} @@ -394,7 +394,7 @@ "type": "text", "placeholders": {} }, - "connect": "Iniciar", + "connect": "Conectar", "@connect": { "type": "text", "placeholders": {} @@ -404,7 +404,7 @@ "type": "text", "placeholders": {} }, - "contactHasBeenInvitedToTheGroup": "El contacto ha sido invitado", + "contactHasBeenInvitedToTheGroup": "El contacto ha sido invitado al grupo", "@contactHasBeenInvitedToTheGroup": { "type": "text", "placeholders": {} @@ -414,7 +414,7 @@ "type": "text", "placeholders": {} }, - "copiedToClipboard": "Copiado al portapapeles!", + "copiedToClipboard": "Copiado al portapapeles", "@copiedToClipboard": { "type": "text", "placeholders": {} @@ -590,7 +590,7 @@ "type": "text", "placeholders": {} }, - "editRoomAliases": "Editar alias del chat", + "editRoomAliases": "Editar alias de la sala", "@editRoomAliases": { "type": "text", "placeholders": {} @@ -605,7 +605,7 @@ "type": "text", "placeholders": {} }, - "emotePacks": "Paquetes de emoticonos para el chat", + "emotePacks": "Paquetes de emoticonos para la habitación", "@emotePacks": { "type": "text", "placeholders": {} @@ -672,7 +672,7 @@ "type": "text", "placeholders": {} }, - "enterAnEmailAddress": "Introduzca un correo electrónico", + "enterAnEmailAddress": "Introducir una dirección de correo electrónico", "@enterAnEmailAddress": { "type": "text", "placeholders": {} @@ -754,12 +754,12 @@ "displayname": {} } }, - "guestsAreForbidden": "Los usuarios visitantes están prohibidos", + "guestsAreForbidden": "Los visitantes están prohibidos", "@guestsAreForbidden": { "type": "text", "placeholders": {} }, - "guestsCanJoin": "Los usuarios visitantes pueden unirse", + "guestsCanJoin": "Los visitantes pueden unirse", "@guestsCanJoin": { "type": "text", "placeholders": {} @@ -802,7 +802,7 @@ "type": "text", "placeholders": {} }, - "ignoredUsers": "Usuarios bloqueados", + "ignoredUsers": "Usuarios ignorados", "@ignoredUsers": { "type": "text", "placeholders": {} @@ -852,7 +852,7 @@ "type": "text", "placeholders": {} }, - "inviteText": "{username} le invitó a FluffyChat.\n1. Instale FluffyChat: https://fluffychat.im\n2. Regístrese o inicia sesión \n3. Abra el enlace de invitación: {link}", + "inviteText": "{username} te invitó a FluffyChat.\n1. Instale FluffyChat: https://fluffychat.im\n2. Regístrate o inicia sesión \n3. Abra el enlace de invitación: {link}", "@inviteText": { "type": "text", "placeholders": { @@ -877,7 +877,7 @@ "username": {} } }, - "joinRoom": "Unirse al chat", + "joinRoom": "Unirse a la sala", "@joinRoom": { "type": "text", "placeholders": {} @@ -908,7 +908,7 @@ "targetName": {} } }, - "kickFromChat": "Eliminar del chat", + "kickFromChat": "Echar del chat", "@kickFromChat": { "type": "text", "placeholders": {} @@ -967,7 +967,7 @@ "type": "text", "placeholders": {} }, - "login": "Iniciar sesión", + "login": "Acceso", "@login": { "type": "text", "placeholders": {} @@ -1066,7 +1066,7 @@ "type": "text", "placeholders": {} }, - "noEncryptionForPublicRooms": "Sólo se puede activar el cifrado en cuanto el chat deja de ser de acceso público.", + "noEncryptionForPublicRooms": "Sólo se puede activar el cifrado en cuanto la sala deja de ser de acceso público.", "@noEncryptionForPublicRooms": { "type": "text", "placeholders": {} @@ -1096,7 +1096,7 @@ "type": "text", "placeholders": {} }, - "noRoomsFound": "Ningún chat encontrado…", + "noRoomsFound": "Ninguna sala encontrada…", "@noRoomsFound": { "type": "text", "placeholders": {} @@ -1205,7 +1205,7 @@ "type": "text", "placeholders": {} }, - "pleaseClickOnLink": "Haga clic en el enlace del correo electrónico y luego continúe. En casos excepcionales, el correo electrónico puede enviarse a spam o tardar hasta 5 minutos en llegar.", + "pleaseClickOnLink": "Haga clic en el enlace del correo electrónico y luego continúe.", "@pleaseClickOnLink": { "type": "text", "placeholders": {} @@ -1245,7 +1245,7 @@ "type": "text", "placeholders": {} }, - "publicRooms": "Chats públicos", + "publicRooms": "Salas públicas", "@publicRooms": { "type": "text", "placeholders": {} @@ -1336,12 +1336,12 @@ "type": "text", "placeholders": {} }, - "roomHasBeenUpgraded": "El chat ha subido de categoría", + "roomHasBeenUpgraded": "La sala ha subido de categoría", "@roomHasBeenUpgraded": { "type": "text", "placeholders": {} }, - "roomVersion": "Versión de chat", + "roomVersion": "Versión de sala", "@roomVersion": { "type": "text", "placeholders": {} @@ -1527,45 +1527,8 @@ "type": "text", "placeholders": {} }, - "sender": "", - "@sender": {}, - "pinMessage": "", - "@pinMessage": {}, - "confirmEventUnpin": "", - "@confirmEventUnpin": {}, - "emojis": "", - "@emojis": {}, "placeCall": "", "@placeCall": {}, - "voiceCall": "Llamada de voz", - "@voiceCall": {}, - "unsupportedAndroidVersion": "", - "@unsupportedAndroidVersion": {}, - "unsupportedAndroidVersionLong": "", - "@unsupportedAndroidVersionLong": {}, - "videoCallsBetaWarning": "", - "@videoCallsBetaWarning": {}, - "experimentalVideoCalls": "", - "@experimentalVideoCalls": {}, - "indexedDbErrorTitle": "", - "@indexedDbErrorTitle": {}, - "indexedDbErrorLong": "", - "@indexedDbErrorLong": {}, - "reactedWith": "{sender} reaccionó con {reaction}", - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "switchToAccount": "", - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, "showPassword": "Mostrar contraseña", "@showPassword": { "type": "text", @@ -1598,7 +1561,7 @@ "type": "text", "placeholders": {} }, - "statusExampleMessage": "¿Cómo está hoy?", + "statusExampleMessage": "¿Cómo estás hoy?", "@statusExampleMessage": { "type": "text", "placeholders": {} @@ -1871,7 +1834,7 @@ "type": "text", "placeholders": {} }, - "wallpaper": "Fondo de pantalla", + "wallpaper": "Fondo de pantalla:", "@wallpaper": { "type": "text", "placeholders": {} @@ -1892,7 +1855,7 @@ "type": "text", "placeholders": {} }, - "weSentYouAnEmail": "Le enviamos un correo electrónico", + "weSentYouAnEmail": "Te enviamos un correo electrónico", "@weSentYouAnEmail": { "type": "text", "placeholders": {} @@ -1912,7 +1875,7 @@ "type": "text", "placeholders": {} }, - "you": "usted", + "you": "Tú", "@you": { "type": "text", "placeholders": {} @@ -1922,7 +1885,7 @@ "type": "text", "placeholders": {} }, - "youAreNoLongerParticipatingInThisChat": "Ya no está participando en este chat", + "youAreNoLongerParticipatingInThisChat": "Ya no estás participando en este chat", "@youAreNoLongerParticipatingInThisChat": { "type": "text", "placeholders": {} @@ -1932,7 +1895,7 @@ "type": "text", "placeholders": {} }, - "youHaveBeenBannedFromThisChat": "Ha sido vetado de este chat", + "youHaveBeenBannedFromThisChat": "Has sido vetado de este chat", "@youHaveBeenBannedFromThisChat": { "type": "text", "placeholders": {} @@ -1969,7 +1932,7 @@ "type": "text", "placeholders": {} }, - "addToSpace": "Agregar a espacio", + "addToSpace": "Agregar al espacio", "@addToSpace": {}, "cantOpenUri": "No puedo abrir el URI {uri}", "@cantOpenUri": { @@ -2043,7 +2006,7 @@ "type": "text", "placeholders": {} }, - "status": "Status", + "status": "Estado", "@status": { "type": "text", "placeholders": {} @@ -2073,7 +2036,7 @@ "type": "text", "placeholders": {} }, - "directChats": "Chat privado", + "directChats": "Chat directo", "@directChats": { "type": "text", "placeholders": {} @@ -2112,10 +2075,7 @@ "type": "text", "placeholders": {} }, - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, + "@chatHasBeenAddedToThisSpace": {}, "commandInvalid": "Comando inválido", "@commandInvalid": { "type": "text" @@ -2177,7 +2137,7 @@ "type": "text", "placeholders": {} }, - "inoffensive": "Un poco ofensivo", + "inoffensive": "Inofensivo", "@inoffensive": { "type": "text", "placeholders": {} @@ -2187,11 +2147,6 @@ "type": "text", "placeholders": {} }, - "soundVibrationLedColor": "Sonido, vibración LED de color", - "@soundVibrationLedColor": { - "type": "text", - "placeholders": {} - }, "memberChanges": "Cambios de miembros", "@memberChanges": { "type": "text", @@ -2207,9 +2162,7 @@ "type": "text", "placeholders": {} }, - "enterASpacepName": "Introduzca un nombre", - "@enterASpacepName": {}, - "ignore": "Bloquear", + "ignore": "Ignorar", "@ignore": { "type": "text", "placeholders": {} @@ -2224,7 +2177,7 @@ "type": "text", "placeholders": {} }, - "offensive": "Ofensivo", + "offensive": "Ofensiva", "@offensive": { "type": "text", "placeholders": {} @@ -2236,12 +2189,12 @@ "type": "text", "placeholders": {} }, - "replaceRoomWithNewerVersion": "Reemplazar chat con una versión más nueva", + "replaceRoomWithNewerVersion": "Reemplazar habitación con una versión más nueva", "@replaceRoomWithNewerVersion": { "type": "text", "placeholders": {} }, - "contentHasBeenReported": "El contenido ha sido reportado", + "contentHasBeenReported": "El contenido ha sido reportado a los administradores del servidor", "@contentHasBeenReported": { "type": "text", "placeholders": {} @@ -2372,17 +2325,17 @@ "type": "text", "placeholders": {} }, - "fontSize": "Tamaño de letra", + "fontSize": "Tamaño de fuente", "@fontSize": { "type": "text", "placeholders": {} }, - "commandHint_ban": "Bloquear el usario de este chat", + "commandHint_ban": "Prohibir al usuario dado en esta sala", "@commandHint_ban": { "type": "text", "description": "Usage hint for the command /ban" }, - "commandHint_unban": "Desbloquear al usuario dado en este chat", + "commandHint_unban": "Des banear al usuario dado en esta sala", "@commandHint_unban": { "type": "text", "description": "Usage hint for the command /unban" @@ -2416,13 +2369,13 @@ "@shareYourInviteLink": {}, "typeInInviteLinkManually": "Escriba el enlace de invitación manualmente...", "@typeInInviteLinkManually": {}, - "scanQrCode": "Escanear código QR", - "@scanQrCode": {}, "unlockChatBackup": "Desbloquear la copia de seguridad del chat", "@unlockChatBackup": { "type": "text", "placeholders": {} }, + "scanQrCode": "Escanear código QR", + "@scanQrCode": {}, "homeserver": "Homeserver", "@homeserver": {}, "newChat": "Nuevo chat", @@ -2430,19 +2383,19 @@ "type": "text", "placeholders": {} }, - "commandHint_join": "Únase al chat indicado", + "commandHint_join": "Únete a la sala indicada", "@commandHint_join": { "type": "text", "description": "Usage hint for the command /join" }, - "sendOnEnter": "Enviar siempre con enter", + "sendOnEnter": "Enviar con enter", "@sendOnEnter": {}, "changeYourAvatar": "Cambiar tu avatar", "@changeYourAvatar": { "type": "text", "placeholders": {} }, - "commandHint_me": "Descríbase", + "commandHint_me": "Descríbete", "@commandHint_me": { "type": "text", "description": "Usage hint for the command /me" @@ -2452,32 +2405,32 @@ "type": "text", "description": "Usage hint for the command /html" }, - "commandHint_invite": "Invitar al usuario indicado a este chat", + "commandHint_invite": "Invitar al usuario indicado a esta sala", "@commandHint_invite": { "type": "text", "description": "Usage hint for the command /invite" }, - "commandHint_kick": "Eliminar el usuario indicado de este chat", + "commandHint_kick": "Eliminar el usuario indicado de esta sala", "@commandHint_kick": { "type": "text", "description": "Usage hint for the command /kick" }, - "commandHint_leave": "Salir de este chat", + "commandHint_leave": "Deja esta sala", "@commandHint_leave": { "type": "text", "description": "Usage hint for the command /leave" }, - "commandHint_myroomavatar": "Seleccione su foto para este chat (by mxc-uri)", + "commandHint_myroomavatar": "Selecciona tu foto para esta sala (by mxc-uri)", "@commandHint_myroomavatar": { "type": "text", "description": "Usage hint for the command /myroomavatar" }, - "commandHint_myroomnick": "Establezca su nombre para mostrar para este chat", + "commandHint_myroomnick": "Establece tu nombre para mostrar para esta sala", "@commandHint_myroomnick": { "type": "text", "description": "Usage hint for the command /myroomnick" }, - "commandHint_op": "Establezca el nivel de potencia del usuario dado (default: 50)", + "commandHint_op": "Establece el nivel de potencia del usuario dado (default: 50)", "@commandHint_op": { "type": "text", "description": "Usage hint for the command /op" @@ -2502,7 +2455,7 @@ "type": "text", "placeholders": {} }, - "editRoomAvatar": "Editar avatar de chat", + "editRoomAvatar": "Editar avatar de sala", "@editRoomAvatar": { "type": "text", "placeholders": {} @@ -2517,7 +2470,7 @@ "type": "text", "placeholders": {} }, - "goToTheNewRoom": "Ir al nuevo chat", + "goToTheNewRoom": "Ir a la nueva sala", "@goToTheNewRoom": { "type": "text", "placeholders": {} @@ -2580,7 +2533,7 @@ "type": "text", "placeholders": {} }, - "spaceName": "Nombre", + "spaceName": "Nombre del espacio", "@spaceName": { "type": "text", "placeholders": {} @@ -2632,7 +2585,7 @@ "@yourUserId": {}, "setupChatBackup": "Configurar copia de respaldo de chat", "@setupChatBackup": {}, - "commandHint_clearcache": "limpiar cache", + "commandHint_clearcache": "Limpiar cache", "@commandHint_clearcache": { "type": "text", "description": "Usage hint for the command /clearcache" @@ -2652,8 +2605,6 @@ "@passwordsDoNotMatch": {}, "pleaseEnterValidEmail": "Por favor ingrese un correo electrónico válido.", "@pleaseEnterValidEmail": {}, - "repeatPassword": "Repetir la contraseña", - "@repeatPassword": {}, "pleaseChooseAtLeastChars": "Por favor elegir al menos {min} carácteres", "@pleaseChooseAtLeastChars": { "type": "text", @@ -2661,6 +2612,9 @@ "min": {} } }, + "repeatPassword": "Repita la contraseña", + "@repeatPassword": {}, + "@addToSpaceDescription": {}, "openGallery": "Abrir galería", "@openGallery": {}, "start": "Iniciar", @@ -2689,8 +2643,6 @@ }, "pleaseEnterSecurityKeyDescription": "Para desbloquear el respaldo de tu chat, por favor ingresa tu clave de seguridad que ha sido generada en una sesión previa. Tu clave de seguridad NO es tu contraseña.", "@pleaseEnterSecurityKeyDescription": {}, - "publish": "Publicar", - "@publish": {}, "updateLanguage": "Cambiar mis idiomas", "@updateLanguage": { "type": "text", @@ -3155,9 +3107,6 @@ "notYetSet": "Aún no está establecido.", "allSuggestedRoomsJoined": "", "suggestedRooms": "Chats sugeridos", - "emailOrUsername": "Nombre de usuario", - "@emailOrUsername": {}, - "connectedToStaging": "Estás conectado al servidor de ensayo.", "partTitle": "Tiene un error de gramática.", "partDesc": "Vea las correcciones sugeridas a continuación.", "punctTitle": "Tiene un error de puntuación.", @@ -3239,7 +3188,6 @@ "timeOfLastMessage": "Hora del último mensaje enviado", "totalMessages": "Mensajes totales enviados", "changeDateRange": "Cambiar rango de fechas", - "doNotShowAgain": "", "l1SpanAndGrammarTitle": "Fuera del idioma de destino", "l1SpanAndGrammarDesc": "Esto podría estar en su idioma base o podría ser un error gramatical.", "allCorrect": "¡Así es como lo diría yo! ¡Muy bien!", @@ -3298,11 +3246,6 @@ "waTooltip": "Uso de L2 sin asistencia", "unTooltip": "Otra", "interactiveGrammarSliderHeader": "Asistencia gramatical", - "allRooms": "", - "@allRooms": { - "type": "text", - "placeholders": {} - }, "errorDisableIT": "La asistencia de traducción está deshabilitada.", "errorDisableIGC": "La asistencia gramatical está deshabilitada.", "errorDisableLanguageAssistance": "La asistencia tanto de traducción como de gramática está deshabilitada.", @@ -3388,43 +3331,12 @@ "type": "text", "placeholders": {} }, - "user": "", - "@user": {}, - "custom": "", - "@custom": {}, - "foregroundServiceRunning": "", - "@foregroundServiceRunning": {}, - "screenSharingTitle": "", - "@screenSharingTitle": {}, - "screenSharingDetail": "", - "@screenSharingDetail": {}, - "callingPermissions": "", - "@callingPermissions": {}, "callingAccount": "", "@callingAccount": {}, - "callingAccountDetails": "", - "@callingAccountDetails": {}, - "appearOnTop": "", - "@appearOnTop": {}, "appearOnTopDetails": "", "@appearOnTopDetails": {}, - "otherCallingPermissions": "Micrófono, cámara y otros permisos de FluffyChat", - "@otherCallingPermissions": {}, - "whyIsThisMessageEncrypted": "", - "@whyIsThisMessageEncrypted": {}, "noKeyForThisMessage": "", "@noKeyForThisMessage": {}, - "newGroup": "Nuevo chat", - "@newGroup": {}, - "enterRoom": "", - "@enterRoom": {}, - "numChats": "", - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, "numberRoomMembers": "{number} miembros", "@numberRoomMembers": { "type": "number", @@ -3432,182 +3344,130 @@ "number": {} } }, - "hideUnimportantStateEvents": "", - "wasDirectChatDisplayName": "", - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "startFirstChat": "", - "nextAccount": "Próxima cuenta", - "@nextAccount": {}, - "previousAccount": "Cuenta anterior", - "@previousAccount": {}, "editWidgets": "", "@editWidgets": {}, - "addWidget": "", - "@addWidget": {}, - "widgetVideo": "", - "@widgetVideo": {}, - "widgetEtherpad": "Nota de texto", - "@widgetEtherpad": {}, + "publish": "Publicar", + "@publish": {}, + "widgetUrlError": "Esta no es una URL válida.", + "@widgetUrlError": {}, + "nextAccount": "Siguiente cuenta", + "@nextAccount": {}, + "youRejectedTheInvitation": "Rechazaste la invitación", + "@youRejectedTheInvitation": {}, + "newGroup": "Nuevo grupo", + "@newGroup": {}, "widgetJitsi": "Jitsi Meet", "@widgetJitsi": {}, - "widgetCustom": "", - "@widgetCustom": {}, - "widgetName": "Nombre", - "@widgetName": {}, - "widgetUrlError": "Esto no es un enlace válido.", - "@widgetUrlError": {}, - "widgetNameError": "", - "@widgetNameError": {}, - "errorAddingWidget": "", - "@errorAddingWidget": {}, - "youRejectedTheInvitation": "Rechazó la invitación.", - "@youRejectedTheInvitation": {}, - "youJoinedTheChat": "", - "@youJoinedTheChat": {}, - "youAcceptedTheInvitation": "👍 Aceptaste la invitación", - "@youAcceptedTheInvitation": {}, - "youBannedUser": "", - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "youHaveWithdrawnTheInvitationFor": "", - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "youInvitedBy": "📩 Ha sido invitado por {user}", + "previousAccount": "Cuenta anterior", + "@previousAccount": {}, + "youInvitedBy": "📩 Has sido invitado por {user}", "@youInvitedBy": { "placeholders": { "user": {} } }, - "commandHint_cuddle": "Enviar un arrunche.", - "@commandHint_cuddle": {}, - "supposedMxid": "Esto debe ser {mxid}", - "youInvitedUser": "", - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "youKicked": "", - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "youKickedAndBanned": "", - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "youUnbannedUser": "", - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, "noEmailWarning": "", "@noEmailWarning": {}, "stories": "Historias", "@stories": {}, "users": "Usuarios", "@users": {}, - "unlockOldMessages": "", - "@unlockOldMessages": {}, - "storeInSecureStorageDescription": "", - "@storeInSecureStorageDescription": {}, - "saveKeyManuallyDescription": "", - "@saveKeyManuallyDescription": {}, - "storeInAndroidKeystore": "", - "@storeInAndroidKeystore": {}, - "storeInAppleKeyChain": "", - "@storeInAppleKeyChain": {}, - "storeSecurlyOnThisDevice": "", - "@storeSecurlyOnThisDevice": {}, - "countFiles": "{count} archivos", - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "confirmMatrixId": "Confirme su ID de Matrix para eliminar su cuenta.", - "@confirmMatrixId": {}, + "youAcceptedTheInvitation": "👍 Aceptaste la invitación", + "@youAcceptedTheInvitation": {}, + "widgetEtherpad": "Nota de texto", + "@widgetEtherpad": {}, + "commandHint_cuddle": "Mandar una carantoña", + "@commandHint_cuddle": {}, + "supposedMxid": "Esto debería ser {mxid}", "@supposedMxid": { "type": "text", "placeholders": { "mxid": {} } }, - "commandHint_googly": "", - "commandHint_hug": "Enviar un abrazo.", - "googlyEyesContent": "", - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "cuddleContent": "", - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "hugContent": "{senderName} le abraza.", + "@importFromZipFile": {}, + "@exportEmotePack": {}, + "addChatDescription": "Añadir una descripción del chat", + "@addChatDescription": {}, + "@sendTypingNotifications": {}, + "@importEmojis": {}, + "confirmMatrixId": "Por favor confirma tu Matrix ID para borrar tu cuenta.", + "@confirmMatrixId": {}, + "@notAnImage": {}, + "commandHint_hug": "Mandar un abrazo", + "@commandHint_hug": {}, + "@importNow": {}, + "hugContent": "{senderName} te abraza", "@hugContent": { "type": "text", "placeholders": { "senderName": {} } }, - "pleaseEnterRecoveryKey": "", - "@pleaseEnterRecoveryKey": {}, - "commandHint_markasdm": "", - "@commandHint_markasdm": {}, "commandHint_markasgroup": "Marcar como grupal", "@commandHint_markasgroup": {}, - "recoveryKey": "", - "@recoveryKey": {}, - "recoveryKeyLost": "", - "@recoveryKeyLost": {}, - "separateChatTypes": "", - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "commandHint_create": "", - "replace": "Corregir", - "@replace": {}, "iUnderstand": "Entiendo", "@iUnderstand": {}, "@encryptThisChat": {}, "@letsStart": {}, "@endToEndEncryption": {}, - "openChat": "Abrir Chat", - "@openChat": {}, "@jumpToLastReadMessage": {}, - "dismiss": "Descartar", - "@dismiss": {}, "@reportErrorDescription": {}, - "@startFirstChat": {}, "setColorTheme": "", "@setColorTheme": {}, + "otherCallingPermissions": "Micrófono, cámara y otros permisos de FluffyChat", + "@otherCallingPermissions": {}, + "emailOrUsername": "Correo electrónico o nombre de usuario", + "@emailOrUsername": {}, + "countFiles": "{count} archivos", + "@countFiles": { + "placeholders": { + "count": {} + } + }, + "voiceCall": "Llamada de voz", + "@voiceCall": {}, + "reactedWith": "{sender} reaccionó con {reaction}", + "@reactedWith": { + "type": "text", + "placeholders": { + "sender": {}, + "reaction": {} + } + }, + "@markAsRead": {}, + "widgetName": "Nombre", + "@widgetName": {}, + "replace": "Reemplazar", + "@replace": {}, + "unsupportedAndroidVersionLong": "Esta característica requiere una versión más reciente de Android. Por favor, compruebe las actualizaciones o la compatibilidad de LineageOS.", + "@unsupportedAndroidVersionLong": {}, + "storeSecurlyOnThisDevice": "Almacenar de forma segura en este dispositivo", + "@storeSecurlyOnThisDevice": {}, + "openChat": "Abrir chat", + "@openChat": {}, + "screenSharingDetail": "Usted está compartiendo su pantalla en FluffyChat", + "@screenSharingDetail": {}, + "allRooms": "Todos los chats grupales", + "@allRooms": { + "type": "text", + "placeholders": {} + }, + "widgetVideo": "Vídeo", + "@widgetVideo": {}, + "dismiss": "Descartar", + "@dismiss": {}, + "unsupportedAndroidVersion": "Versión de Android no compatible", + "@unsupportedAndroidVersion": {}, + "indexedDbErrorLong": "El almacenamiento de mensajes, por desgracia, no está habilitado en el modo privado por defecto.\nPor favor, visite\n - about:config\n - Establezca dom.indexedDB.privateBrowsing.enabled a true\nDe otra forma, no es posible usar FluffyChat.", + "@indexedDbErrorLong": {}, + "startFirstChat": "Comience su primer chat", + "@startFirstChat": {}, + "commandHint_create": "Crear un chat grupal vacío\nUse --no-encryption para deshabilitar el cifrado", "@commandHint_create": { "type": "text", "description": "Usage hint for the command /create" }, - "commandHint_dm": "", "banUserDescription": "", "@banUserDescription": {}, "requests": "", @@ -3616,45 +3476,76 @@ "@addToStory": {}, "removeDevicesDescription": "", "@removeDevicesDescription": {}, - "tryAgain": "", - "@tryAgain": {}, "showDirectChatsInSpaces": "Mostrar chats directos relacionados en Spaces", "unbanUserDescription": "", "@unbanUserDescription": {}, "todoLists": "", "@todoLists": {}, - "messagesStyle": "", - "@messagesStyle": {}, "@newSpaceDescription": {}, - "chatDescription": "", - "@chatDescription": {}, - "enterSpace": "Introducir espacio", - "@enterSpace": {}, "@reopenChat": {}, "editTodo": "", "@editTodo": {}, - "hydrateTor": "TOR Usuarios: Importar exportación de sesión", - "@hydrateTor": {}, "pushNotificationsNotAvailable": "", "@pushNotificationsNotAvailable": {}, - "hydrate": "Restaurar desde archivo de copia de seguridad", - "@hydrate": {}, - "invalidServerName": "", - "@invalidServerName": {}, - "chatPermissions": "", - "@chatPermissions": {}, "signInWithPassword": "", "@signInWithPassword": {}, "pleaseAddATitle": "", "@pleaseAddATitle": {}, "makeAdminDescription": "", "@makeAdminDescription": {}, - "setChatDescription": "", - "@setChatDescription": {}, - "dehydrateWarning": "Esta acción no se puede deshacer. Asegúrese de almacenar de forma segura el archivo de copia de seguridad.", - "@dehydrateWarning": {}, "@noOtherDevicesFound": {}, - "redactedBy": "", + "user": "Usuario", + "@user": {}, + "separateChatTypes": "Separar chats directos de grupos", + "@separateChatTypes": { + "type": "text", + "placeholders": {} + }, + "tryAgain": "Inténtelo de nuevo", + "@tryAgain": {}, + "youKickedAndBanned": "🙅 Usted expulsó y prohibió el acceso a {user}", + "@youKickedAndBanned": { + "placeholders": { + "user": {} + } + }, + "messagesStyle": "Mensajes:", + "@messagesStyle": {}, + "chatDescription": "Descripción del chat", + "@chatDescription": {}, + "callingAccountDetails": "Permite a FluffyChat utilizar la aplicación de llamadas nativa de Android.", + "@callingAccountDetails": {}, + "enterSpace": "Unirse al espacio", + "@enterSpace": {}, + "pleaseEnterRecoveryKey": "Por favor, introduzca su clave de recuperación:", + "@pleaseEnterRecoveryKey": {}, + "widgetNameError": "Por favor, introduzca un nombre a mostrar.", + "@widgetNameError": {}, + "addWidget": "Añadir widget", + "@addWidget": {}, + "hydrateTor": "TOR: Importar sesión exportada", + "@hydrateTor": {}, + "storeInAppleKeyChain": "Almacenar en la KeyChain de Apple", + "@storeInAppleKeyChain": {}, + "hydrate": "Restaurar desde fichero de copia de seguridad", + "@hydrate": {}, + "invalidServerName": "Nombre del servidor no válido", + "@invalidServerName": {}, + "chatPermissions": "Permisos del chat", + "@chatPermissions": {}, + "sender": "Remitente", + "@sender": {}, + "storeInAndroidKeystore": "Almacenar en la KeyStore de Android", + "@storeInAndroidKeystore": {}, + "saveKeyManuallyDescription": "Compartir esta clave manualmente usando el diálogo de compartir del sistema o el portapapeles.", + "@saveKeyManuallyDescription": {}, + "whyIsThisMessageEncrypted": "¿Por qué no se puede leer este mensaje?", + "@whyIsThisMessageEncrypted": {}, + "setChatDescription": "Establecer descripción del chat", + "@setChatDescription": {}, + "dehydrateWarning": "Esta acción no se puede deshacer. Asegúrese de que ha almacenado de forma segura el fichero de copia de seguridad.", + "@dehydrateWarning": {}, + "redactedBy": "Censurado por {username}", "@redactedBy": { "type": "text", "placeholders": { @@ -3676,17 +3567,39 @@ "noTodosYet": "", "@noTodosYet": {}, "@readUpToHere": {}, - "optionalRedactReason": "", - "@optionalRedactReason": {}, - "dehydrate": "Exportar sesión y borrar dispositivo", - "@dehydrate": {}, "archiveRoomDescription": "El chat se moverá al archivo para ti y para otros usuarios que no sean administradores", "@archiveRoomDescription": {}, - "pleaseEnterRecoveryKeyDescription": "Para desbloquear sus mensajes antiguos, ingrese su clave de recuperación que se generó en una sesión anterior. Su clave de recuperación NO es su contraseña.", + "videoCallsBetaWarning": "Tenga en cuenta que las videollamadas están actualmente en fase beta. Es posible que no funcionen como se espera o que no funcionen de ninguna manera en algunas plataformas.", + "@videoCallsBetaWarning": {}, + "callingPermissions": "Permisos de llamadas", + "@callingPermissions": {}, + "unlockOldMessages": "Desbloquear mensajes viejos", + "@unlockOldMessages": {}, + "numChats": "{number} chats", + "@numChats": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "optionalRedactReason": "(Opcional) Motivo para censurar este mensaje...", + "@optionalRedactReason": {}, + "dehydrate": "Exportar sesión y limpiar dispositivo", + "@dehydrate": {}, + "switchToAccount": "Cambiar a la cuenta {number}", + "@switchToAccount": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "experimentalVideoCalls": "Videollamadas experimentales", + "@experimentalVideoCalls": {}, + "pleaseEnterRecoveryKeyDescription": "Para desbloquear sus viejos mensajes, introduzca su clave de recuperación que se generó en una sesión anterior. Su clave de recuperación NO es su contraseña.", "@pleaseEnterRecoveryKeyDescription": {}, - "inviteContactToGroupQuestion": "", + "inviteContactToGroupQuestion": "¿Quieres invitar a {contact} al chat {groupName}?", "@inviteContactToGroupQuestion": {}, - "redactedByBecause": "", + "redactedByBecause": "Censurado por {username} porque: \"{reason}\"", "@redactedByBecause": { "type": "text", "placeholders": { @@ -3696,31 +3609,25 @@ }, "anyoneCanKnock": "", "@anyoneCanKnock": {}, - "redactMessageDescription": "", - "@redactMessageDescription": {}, "invalidInput": "", "@invalidInput": {}, "todosUnencrypted": "", "@todosUnencrypted": {}, - "dehydrateTorLong": "Para TOR usuarios, se recomienda exportar la sesión antes de cerrar la ventana.", - "@dehydrateTorLong": {}, - "@doNotShowAgain": {}, "@report": {}, - "@hideUnimportantStateEvents": {}, "whoCanSeeMyStoriesDesc": "Ten en cuenta que las personas pueden verse y ponerse en contacto en tu historia.", "@whoCanSeeMyStoriesDesc": {}, "unsubscribeStories": "Darse de baja de historias", "@unsubscribeStories": {}, "hasKnocked": "", - "@hasKnocked": { + "@hasKnocked": {}, + "youHaveWithdrawnTheInvitationFor": "Usted retiró la invitación a {user}", + "@youHaveWithdrawnTheInvitationFor": { "placeholders": { "user": {} } }, "@openLinkInBrowser": {}, "@disableEncryptionWarning": {}, - "directChat": "", - "@directChat": {}, "noOneCanJoin": "", "@noOneCanJoin": {}, "wrongPinEntered": "", @@ -3734,16 +3641,10 @@ "@inviteGroupChat": {}, "invitePrivateChat": "", "@invitePrivateChat": {}, - "noChatDescriptionYet": "", - "@noChatDescriptionYet": {}, "newTodo": "", "@newTodo": {}, "learnMore": "", "@learnMore": {}, - "chatDescriptionHasBeenChanged": "", - "@chatDescriptionHasBeenChanged": {}, - "dehydrateTor": "TOR Usuarios: Exportar sesión", - "@dehydrateTor": {}, "todoListChangedError": "", "@todoListChangedError": {}, "@enterInviteLinkOrMatrixId": {}, @@ -3763,10 +3664,69 @@ "body": {} } }, - "shareInviteLink": "", - "@shareInviteLink": {}, "@deviceKeys": {}, - "emoteKeyboardNoRecents": "", + "enterRoom": "Unirse a la sala", + "@enterRoom": {}, + "confirmEventUnpin": "¿Seguro que quiere desfijar permanentemente el evento?", + "@confirmEventUnpin": {}, + "youInvitedUser": "📩 Usted invitó a {user}", + "@youInvitedUser": { + "placeholders": { + "user": {} + } + }, + "redactMessageDescription": "El mensaje será censurado para todas las personas participantes en la conversación. Esto no se puede deshacer.", + "@redactMessageDescription": {}, + "recoveryKey": "Clave de recuperación", + "@recoveryKey": {}, + "dehydrateTorLong": "Si está usando TOR, es recomendable exportar la sesión antes de cerrar la ventana.", + "@dehydrateTorLong": {}, + "doNotShowAgain": "No mostrar de nuevo", + "@doNotShowAgain": {}, + "hideUnimportantStateEvents": "Ocultar eventos de estado no importantes", + "@hideUnimportantStateEvents": {}, + "screenSharingTitle": "Compartir la pantalla", + "@screenSharingTitle": {}, + "widgetCustom": "Personalizado", + "@widgetCustom": {}, + "youBannedUser": "Usted prohibió el acceso a {user}", + "@youBannedUser": { + "placeholders": { + "user": {} + } + }, + "directChat": "Chat directo", + "@directChat": {}, + "appearOnTop": "Aparecer en la cima", + "@appearOnTop": {}, + "foregroundServiceRunning": "Esta notificación aparece cuando el servicio en segundo plano se está ejecutando.", + "@foregroundServiceRunning": {}, + "wasDirectChatDisplayName": "Chat vacío (era {oldDisplayName})", + "@wasDirectChatDisplayName": { + "type": "text", + "placeholders": { + "oldDisplayName": {} + } + }, + "noChatDescriptionYet": "No se ha creado una descripción del chat aún.", + "@noChatDescriptionYet": {}, + "chatDescriptionHasBeenChanged": "Se ha cambiado la descripción del chat", + "@chatDescriptionHasBeenChanged": {}, + "dehydrateTor": "TOR: Exportar sesión", + "@dehydrateTor": {}, + "youKicked": "👞 Usted expulsó a {user}", + "@youKicked": { + "placeholders": { + "user": {} + } + }, + "shareInviteLink": "Compartir enlace de invitación", + "@shareInviteLink": {}, + "commandHint_markasdm": "Marcar como sala de mensajes directos para el ID de Matrix", + "@commandHint_markasdm": {}, + "recoveryKeyLost": "¿Perdió su clave de recuperación?", + "@recoveryKeyLost": {}, + "emoteKeyboardNoRecents": "Los emotes usados recientemente aparecerán aquí...", "@emoteKeyboardNoRecents": { "type": "text", "placeholders": {} @@ -3775,12 +3735,15 @@ "@setTheme": {}, "thisUserHasNotPostedAnythingYet": "Este usuario aún no ha publicado nada en su historia.", "@thisUserHasNotPostedAnythingYet": {}, + "youJoinedTheChat": "Usted se ha unido al chat", + "@youJoinedTheChat": {}, + "errorAddingWidget": "Fallo al añadir el widget.", + "@errorAddingWidget": {}, + "commandHint_dm": "Iniciar un chat directo\nUse --no-encryption para deshabilitar el cifrado", "@commandHint_dm": { "type": "text", "description": "Usage hint for the command /dm" }, - "hydrateTorLong": "", - "@hydrateTorLong": {}, "reportUser": "Reportar usuario", "@reportUser": {}, "markAsRead": "Marcar como leído", @@ -4542,7 +4505,7 @@ "age": {} } }, - "selectToDefine": "Haga doble clic en una palabra para ver su definición.", + "selectToDefine": "¡Resalta una palabra o frase para ver su definición!", "kickBotWarning": "Patear Pangea Bot eliminará el bot de conversación de este chat.", "activateTrial": "Activar prueba gratuita", "refresh": "Actualizar", @@ -4737,5 +4700,41 @@ "description": "El número de compilación de la aplicación." } } - } + }, + "youUnbannedUser": "Usted volvió a permitir el acceso a {user}", + "@youUnbannedUser": { + "placeholders": { + "user": {} + } + }, + "emojis": "Emojis", + "@emojis": {}, + "createGroup": "Crear grupo", + "@createGroup": {}, + "hydrateTorLong": "¿Exportó su sesión la última vez que estuvo en TOR? Impórtela rápidamente y continúe chateando.", + "@hydrateTorLong": {}, + "custom": "Personalizado", + "@custom": {}, + "storeInSecureStorageDescription": "Almacenar la clave de recuperación en el almacenamiento seguro de este dispositivo.", + "@storeInSecureStorageDescription": {}, + "pinMessage": "Anclar a la sala", + "@pinMessage": {}, + "indexedDbErrorTitle": "Problemas con el modo privado", + "@indexedDbErrorTitle": {}, + "googlyEyesContent": "{senderName} te manda ojos saltones", + "@googlyEyesContent": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "cuddleContent": "{senderName} se acurruca contigo", + "@cuddleContent": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "commandHint_googly": "Enviar unos ojos saltones", + "@commandHint_googly": {} } \ No newline at end of file diff --git a/assets/l10n/intl_et.arb b/assets/l10n/intl_et.arb index 649199cc5..f702beb5a 100644 --- a/assets/l10n/intl_et.arb +++ b/assets/l10n/intl_et.arb @@ -559,7 +559,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "Vaikimisi õigused", + "defaultPermissionLevel": "Vaikimisi õigused uutele kasutajatele", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -1085,7 +1085,7 @@ "type": "text", "placeholders": {} }, - "noGoogleServicesWarning": "Tundub, et sinu nutiseadmes pole Firebase Cloud Messaging teenuseid. Sinu privaatsuse mõttes on see kindlasti hea otsus! Kui sa soovid FluffyChat'is näha tõuketeavitusi, siis soovitame, et selle jaoks kasutad ntfy liidestust. Kasutades ntfy'd või mõnda muud Unified Push standardil põhinevat liidestust saad tõuketeavitusi turvalisel moel. Ntfy rakendus on saadaval nii PlayStore kui F-Droid'i rakendusepoodides.", + "noGoogleServicesWarning": "Tundub, et sinu nutiseadmes pole Firebase Cloud Messaging teenuseid. Sinu privaatsuse mõttes on see kindlasti hea otsus! Kui sa soovid FluffyChatis näha tõuketeavitusi, siis soovitame, et selle jaoks kasutad ntfy liidestust. Kasutades ntfyd või mõnda muud Unified Push standardil põhinevat liidestust saad tõuketeavitusi turvalisel moel. Ntfy rakendus on saadaval nii PlayStore kui F-Droidi rakendusepoodides.", "@noGoogleServicesWarning": { "type": "text", "placeholders": {} @@ -1150,7 +1150,7 @@ "type": "text", "placeholders": {} }, - "ok": "sobib", + "ok": "Sobib", "@ok": { "type": "text", "placeholders": {} @@ -2020,7 +2020,7 @@ "@emailOrUsername": {}, "experimentalVideoCalls": "Katselised videokõned", "@experimentalVideoCalls": {}, - "unsupportedAndroidVersionLong": "See funktsionaalsus eeldab uuemat Androidi versiooni. Palun kontrolli, kas sinu nutiseadmele leidub süsteemiuuendusi või saaks seal Lineage OS'i kasutada.", + "unsupportedAndroidVersionLong": "See funktsionaalsus eeldab uuemat Androidi versiooni. Palun kontrolli, kas sinu nutiseadmele leidub süsteemiuuendusi või saaks seal Lineage OSi kasutada.", "@unsupportedAndroidVersionLong": {}, "nextAccount": "Järgmine kasutajakonto", "@nextAccount": {}, @@ -2206,7 +2206,7 @@ "@foregroundServiceRunning": {}, "allSpaces": "Kõik kogukonnad", "@allSpaces": {}, - "screenSharingDetail": "Sa jagad oma ekraani FuffyChat'i vahendusel", + "screenSharingDetail": "Sa jagad oma ekraani FuffyChati vahendusel", "@screenSharingDetail": {}, "numChats": "{number} vestlust", "@numChats": { @@ -2706,5 +2706,98 @@ "gallery": "Galerii", "@gallery": {}, "files": "Failid", - "@files": {} + "@files": {}, + "swipeRightToLeftToReply": "Vastamiseks viipa paremalt vasakule", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "false", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "noMoreChatsFound": "Rohkem vestlusi ei leidu...", + "@noMoreChatsFound": {}, + "joinedChats": "Vestlusi, millega oled liitunud", + "@joinedChats": {}, + "unread": "Lugemata", + "@unread": {}, + "space": "Kogukond", + "@space": {}, + "spaces": "Kogukonnad", + "@spaces": {}, + "goToSpace": "Ava kogukond: {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "Märgi mitteloetuks", + "@markAsUnread": {}, + "countChatsAndCountParticipants": "{chats} vestlust ja {participants} osalejat", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "userLevel": "{level} - kasutaja", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - moderaator", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - peakasutaja", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeTheVisibilityOfChatHistory": "Muuda vestluse ajaloo nähtavust", + "@changeTheVisibilityOfChatHistory": {}, + "sendRoomNotifications": "Saada @jututuba teavitusi", + "@sendRoomNotifications": {}, + "changeTheCanonicalRoomAlias": "Muuda vestluse põhilist avalikult nähtavat aadressi", + "@changeTheCanonicalRoomAlias": {}, + "changeGeneralChatSettings": "Muuda vestluse üldiseid seadistusi", + "@changeGeneralChatSettings": {}, + "inviteOtherUsers": "Kutsu teisi osalejaid sellesse vestlusesse", + "@inviteOtherUsers": {}, + "changeTheChatPermissions": "Muuda vestluse õigusi", + "@changeTheChatPermissions": {}, + "changeTheDescriptionOfTheGroup": "Muuda vestluse kirjeldust", + "@changeTheDescriptionOfTheGroup": {}, + "chatPermissionsDescription": "Määra erinevatele kasutajatele selles vestluses vajalikud õigused. Tüüpiliselt on need 0, 50 ja 100 (vastavalt kasutajad, moderaatorid ja peakasutajad), kuid igasugused vahepealsed variatsioonid on ka võimalikud.", + "@chatPermissionsDescription": {}, + "invitedBy": "📩 Kutsujaks {user}", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "updateInstalled": "🎉 Versiooniuuendus {version} on paigaldatud!", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "changelog": "Muudatuste logi", + "@changelog": {}, + "sendCanceled": "Saatmine on katkestatud", + "@sendCanceled": {}, + "noChatsFoundHere": "Siin ei leidu veel ühtegi vestlust. Alusta uut vestlust klõpsides allpool asuvat nuppu. ⤵️", + "@noChatsFoundHere": {}, + "loginWithMatrixId": "Logi sisse Matrix-ID alusel", + "@loginWithMatrixId": {}, + "discoverHomeservers": "Leia koduservereid", + "@discoverHomeservers": {}, + "whatIsAHomeserver": "Mis on koduserver?", + "@whatIsAHomeserver": {} } diff --git a/assets/l10n/intl_eu.arb b/assets/l10n/intl_eu.arb index dd4d35087..f317b99de 100644 --- a/assets/l10n/intl_eu.arb +++ b/assets/l10n/intl_eu.arb @@ -23,7 +23,7 @@ "type": "text", "placeholders": {} }, - "activatedEndToEndEncryption": "🔐 {username}(e)k ertzetik ertzerako zifraketa gaitu du", + "activatedEndToEndEncryption": "🔐 {username}(e)k ertzetik ertzerako zifratzea gaitu du", "@activatedEndToEndEncryption": { "type": "text", "placeholders": { @@ -226,7 +226,7 @@ "type": "text", "placeholders": {} }, - "channelCorruptedDecryptError": "Zifraketa hondatu egin da", + "channelCorruptedDecryptError": "Zifratzea hondatu egin da", "@channelCorruptedDecryptError": { "type": "text", "placeholders": {} @@ -412,17 +412,17 @@ "type": "text", "placeholders": {} }, - "enableEncryptionWarning": "Ezingo duzu zifraketa ezgaitu. Ziur zaude?", + "enableEncryptionWarning": "Ezingo duzu zifratzea ezgaitu. Ziur zaude?", "@enableEncryptionWarning": { "type": "text", "placeholders": {} }, - "encryption": "Zifraketa", + "encryption": "Zifratzea", "@encryption": { "type": "text", "placeholders": {} }, - "encryptionNotEnabled": "Zifraketa ez dago gaituta", + "encryptionNotEnabled": "Zifratzea ez dago gaituta", "@encryptionNotEnabled": { "type": "text", "placeholders": {} @@ -666,7 +666,7 @@ "type": "text", "placeholders": {} }, - "needPantalaimonWarning": "Kontuan izan oraingoz Pantalaimon behar duzula puntuz puntuko zifraketarako.", + "needPantalaimonWarning": "Kontuan izan oraingoz Pantalaimon behar duzula ertzetik ertzerako zifratzerako.", "@needPantalaimonWarning": { "type": "text", "placeholders": {} @@ -1036,7 +1036,7 @@ "type": "text", "placeholders": {} }, - "unknownEncryptionAlgorithm": "Zifraketa-algoritmo ezezaguna", + "unknownEncryptionAlgorithm": "Zifratze-algoritmo ezezaguna", "@unknownEncryptionAlgorithm": { "type": "text", "placeholders": {} @@ -1560,7 +1560,7 @@ "type": "text", "placeholders": {} }, - "contentHasBeenReported": "Edukia zerbitzariko administrariei jakinarazi zaie", + "contentHasBeenReported": "Edukia zerbitzariko administratzaileei jakinarazi zaie", "@contentHasBeenReported": { "type": "text", "placeholders": {} @@ -1649,7 +1649,7 @@ "type": "text", "placeholders": {} }, - "enableEncryption": "Gaitu zifraketa", + "enableEncryption": "Gaitu zifratzea", "@enableEncryption": { "type": "text", "placeholders": {} @@ -1781,7 +1781,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "Defektuzko botere-maila", + "defaultPermissionLevel": "Erabiltzaile berrien defektuzko botere-maila", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -1841,7 +1841,7 @@ "type": "text", "placeholders": {} }, - "noEncryptionForPublicRooms": "Zifraketa aktiba dezakezu soilik gelak publikoa izateari utzi badio.", + "noEncryptionForPublicRooms": "Zifratzea aktiba dezakezu soilik gelak publikoa izateari utzi badio.", "@noEncryptionForPublicRooms": { "type": "text", "placeholders": {} @@ -2161,7 +2161,7 @@ "@hydrateTor": {}, "saveKeyManuallyDescription": "Gorde eskuz gako hau gailuko partekatze-menua edo arbela erabiliz.", "@saveKeyManuallyDescription": {}, - "indexedDbErrorTitle": "Arazoak modu pribatuan", + "indexedDbErrorTitle": "Arazoak modu pribatuarekin", "@indexedDbErrorTitle": {}, "confirmMatrixId": "Baieztatu zure Matrix IDa kontua ezabatu ahal izateko.", "@confirmMatrixId": {}, @@ -2202,7 +2202,7 @@ }, "hideUnimportantStateEvents": "Ezkutatu garrantzirik gabeko gertaerak", "@hideUnimportantStateEvents": {}, - "noKeyForThisMessage": "Mezua gailu honetan saioa hasi baino lehen bidali bazen gertatu daiteke.\n\nBeste aukera bat igorleak zure gailua blokeatu izana da, edo zerbaitek huts egin izana interneteko konexioan.\n\nMezua beste saio batean irakur dezakezu? Hala bada, mezua transferitu dezakezu! Zoaz Ezrpenetara > Gailuak eta baieztatu zure gailuek bata bestea egiaztatu dutela. Gela irakiko duzun hurrengo aldian eta bi saioak aurreko planoan irekita daudenean, gakoak automatikoki partekatuko dira.\n\nEz duzu gakorik galdu nahi saioa amaitu edo gailuak aldatzen dituzunean? Baieztatu ezarpenetan txaten babeskopiak gaituta dituzula.", + "noKeyForThisMessage": "Mezua gailu honetan saioa hasi baino lehen bidali bazen gertatu daiteke.\n\nBeste aukera bat igorleak zure gailua blokeatu izana da, edo zerbaitek huts egin izana interneteko konexioan.\n\nMezua beste saio batean irakur dezakezu? Hala bada, mezua transferitu dezakezu! Zoaz Ezrpenetara > Gailuak eta baieztatu zure gailuek bata bestea egiaztatu dutela. Gela irekiko duzun hurrengo aldian eta bi saioak aurreko planoan irekita daudenean, gakoak automatikoki partekatuko dira.\n\nEz duzu gakorik galdu nahi saioa amaitu edo gailuak aldatzen dituzunean? Baieztatu ezarpenetan txaten babeskopiak gaituta dituzula.", "@noKeyForThisMessage": {}, "supposedMxid": "Hau {mxid} izan behar da", "@supposedMxid": { @@ -2238,7 +2238,7 @@ "@startFirstChat": {}, "newSpaceDescription": "Guneek txatak taldekatzea ahalbidetzen dute eta komunitate pribatu edo publikoak osatzea.", "@newSpaceDescription": {}, - "disableEncryptionWarning": "Segurtasun arrazoiak direla-eta, ezin duzu lehendik zifratuta zegoen txat bateko zifraketa ezgaitu.", + "disableEncryptionWarning": "Segurtasun arrazoiak direla-eta, ezin duzu lehendik zifratuta zegoen txat bateko zifratzea ezgaitu.", "@disableEncryptionWarning": {}, "encryptThisChat": "Zifratu txata", "@encryptThisChat": {}, @@ -2357,7 +2357,7 @@ }, "redactMessageDescription": "Mezua elkarrizketa honetako partaide guztientzat botako da atzera. Ezin da desegin.", "@redactMessageDescription": {}, - "addChatDescription": "Gehitu txat honen deskribapena…", + "addChatDescription": "Gehitu txataren deskribapena…", "@addChatDescription": {}, "directChat": "Banakako txata", "@directChat": {}, @@ -2486,7 +2486,7 @@ "@thisDevice": {}, "decline": "Baztertu", "@decline": {}, - "databaseBuildErrorBody": "Ezin izan da SQlite datu-basea eraiki. Aplikazioa aurreko datu-basea erabiltzen saiatuko da oraingoz. Jakinarazi errorea garatzaileei {url} helbidean. Errorearen mezua ondorengoa da: {error}", + "databaseBuildErrorBody": "Ezin da SQlite datu-basea eraiki. Aplikazioa aurreko datu-basea erabiltzen saiatuko da oraingoz. Jakinarazi errorea garatzaileei {url} helbidean. Errorearen mezua ondorengoa da: {error}", "@databaseBuildErrorBody": { "type": "text", "placeholders": { @@ -2520,7 +2520,7 @@ }, "transparent": "Gardena", "@transparent": {}, - "sendReadReceipts": "Bidali irakurri izanaren adierazlea", + "sendReadReceipts": "Bidali irakurri izanaren agiria", "@sendReadReceipts": {}, "formattedMessages": "Formatua duten mezuak", "@formattedMessages": {}, @@ -2547,7 +2547,7 @@ "sender": {} } }, - "sendReadReceiptsDescription": "Txateko beste kideek mezu bat irakurri duzula ikus dezakete.", + "sendReadReceiptsDescription": "Txateko beste partaideek mezu bat irakurri duzula ikus dezakete.", "@sendReadReceiptsDescription": {}, "forwardMessageTo": "Birbidali mezua {roomName}(e)ra?", "@forwardMessageTo": { @@ -2576,7 +2576,7 @@ "@verifyOtherUserDescription": {}, "formattedMessagesDescription": "Erakutsi mezu aberatsen edukia markdown erabiliz, testu lodia esaterako.", "@formattedMessagesDescription": {}, - "sendTypingNotificationsDescription": "Txateko beste kideek mezu berri bat idazten ari zarela ikus dezakete.", + "sendTypingNotificationsDescription": "Txateko beste partaideek mezu berri bat idazten ari zarela ikus dezakete.", "@sendTypingNotificationsDescription": {}, "verifyOtherUser": "🔐 Egiaztatu beste erabiltzaile bat", "@verifyOtherUser": {}, @@ -2679,7 +2679,7 @@ "@noPublicLinkHasBeenCreatedYet": {}, "userRole": "Erabiltzailearen rola", "@userRole": {}, - "minimumPowerLevel": "{level} da gutxieneko botere maila.", + "minimumPowerLevel": "{level} da gutxieneko botere-maila.", "@minimumPowerLevel": { "type": "text", "placeholders": { @@ -2694,7 +2694,7 @@ "@files": {}, "gallery": "Galeria", "@gallery": {}, - "searchIn": "Bilatu {chat}ean...", + "searchIn": "Bilatu {chat} txatean...", "@searchIn": { "type": "text", "placeholders": { @@ -2702,5 +2702,106 @@ } }, "searchMore": "Bilatu gehiago...", - "@searchMore": {} + "@searchMore": {}, + "restricted": "Mugatuta", + "@restricted": {}, + "knockRestricted": "Eskatu baimena sarrera mugatua duen txatean", + "@knockRestricted": {}, + "swipeRightToLeftToReply": "Herrestatu eskuin-ezker erantzuteko", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "false", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "noMoreChatsFound": "Ez da beste txatik aurkitu...", + "@noMoreChatsFound": {}, + "unread": "Irakurri gabe", + "@unread": {}, + "space": "Gunea", + "@space": {}, + "joinedChats": "Batu zaren txatak", + "@joinedChats": {}, + "goToSpace": "Joan {space} gunera", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "Markatu irakurri gabetzat", + "@markAsUnread": {}, + "countChatsAndCountParticipants": "{chats} txat eta {participants} partaide", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "spaces": "Guneak", + "@spaces": {}, + "adminLevel": "{level} - Administratzailea", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeTheChatPermissions": "Aldatu txataren baimenak", + "@changeTheChatPermissions": {}, + "inviteOtherUsers": "Gonbidatu beste erabiltzaileak txat honetara", + "@inviteOtherUsers": {}, + "userLevel": "{level} - Erabiltzailea", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - Moderatzailea", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "sendRoomNotifications": "Bidali @gela jakinarazpena", + "@sendRoomNotifications": {}, + "changeTheDescriptionOfTheGroup": "Aldatu txataren deskribapena", + "@changeTheDescriptionOfTheGroup": {}, + "changeGeneralChatSettings": "Aldatu txataren ezarpen orokorrak", + "@changeGeneralChatSettings": {}, + "changeTheVisibilityOfChatHistory": "Aldatu txataren historiaren ikusgaitasuna", + "@changeTheVisibilityOfChatHistory": {}, + "changeTheCanonicalRoomAlias": "Aldatu txataren helbide publiko nagusia", + "@changeTheCanonicalRoomAlias": {}, + "invitedBy": "📩 {user}(e)k gonbidatua", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "updateInstalled": "🎉 {version} bertsioa instalatu da!", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "changelog": "Aldaketak", + "@changelog": {}, + "chatPermissionsDescription": "Definitu zer botere-maila behar den txat honetako ekintza jakinetarako. 0, 50 eta 100 botere-mailek erabiltzaileak, moderatzaileak eta administratzaileak ordezkatzen dituzte, baina edozein graduazio posible da.", + "@chatPermissionsDescription": {}, + "sendCanceled": "Bidalketa bertan behera utzi da", + "@sendCanceled": {}, + "noChatsFoundHere": "Ez da txatik aurkitu. Hasi norbaitekin txateatzen beheko botoia erabiliz. ⤵️", + "@noChatsFoundHere": {}, + "homeserverDescription": "Zerbitzariak datuak gordetzen ditu, ePosta hornitzaileek mezuak gordetzen dituzten bezala. Nahi duzun zerbitzaria aukeratu dezakezu eta, hala ere, besteetako edonorekin hitz egin. Ikasi gehiago https://matrix.org webgunean.", + "@homeserverDescription": {}, + "loginWithMatrixId": "Hasi saioa Matrix IDarekin", + "@loginWithMatrixId": {}, + "discoverHomeservers": "Arakatu zerbitzariak", + "@discoverHomeservers": {}, + "whatIsAHomeserver": "Zer da zerbitzari bat?", + "@whatIsAHomeserver": {}, + "doesNotSeemToBeAValidHomeserver": "Ez dirudi zerbitzaria bateragarria denik. Zuzena da URLa?", + "@doesNotSeemToBeAValidHomeserver": {} } diff --git a/assets/l10n/intl_fa.arb b/assets/l10n/intl_fa.arb index b51439b8e..d62cb8884 100644 --- a/assets/l10n/intl_fa.arb +++ b/assets/l10n/intl_fa.arb @@ -2300,78 +2300,6 @@ "@signInWithPassword": {}, "pleaseTryAgainLaterOrChooseDifferentServer": "لطفا بعدا تلاش کنید یا سرور دیگری انتخاب کنید.", "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@setColorTheme": {}, - "@banUserDescription": {}, - "@removeDevicesDescription": {}, - "@tryAgain": {}, - "@unbanUserDescription": {}, - "@messagesStyle": {}, - "@chatDescription": {}, - "@pushNotificationsNotAvailable": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@makeAdminDescription": {}, - "@setChatDescription": {}, - "@importFromZipFile": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@optionalRedactReason": {}, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@redactMessageDescription": {}, - "@invalidInput": {}, - "@addChatDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@invitePrivateChat": {}, - "@importEmojis": {}, - "@noChatDescriptionYet": {}, - "@learnMore": {}, "notAnImage": "یک فایل تصویری نیست.", - "@notAnImage": {}, - "@chatDescriptionHasBeenChanged": {}, - "@roomUpgradeDescription": {}, - "@pleaseEnterANumber": {}, - "@profileNotFound": {}, - "@shareInviteLink": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@replace": {}, - "@createGroup": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@invite": {} + "@notAnImage": {} } diff --git a/assets/l10n/intl_fi.arb b/assets/l10n/intl_fi.arb index 65465acfd..b9123ff0f 100644 --- a/assets/l10n/intl_fi.arb +++ b/assets/l10n/intl_fi.arb @@ -2402,12 +2402,5 @@ "importNow": "Tuo nyt", "@importNow": {}, "invite": "Kutsu", - "@invite": {}, - "@banUserDescription": {}, - "@removeDevicesDescription": {}, - "@unbanUserDescription": {}, - "@pushNotificationsNotAvailable": {}, - "@makeAdminDescription": {}, - "@learnMore": {}, - "@kickUserDescription": {} + "@invite": {} } diff --git a/assets/l10n/intl_fr.arb b/assets/l10n/intl_fr.arb index ba0a82634..7c8c317e2 100644 --- a/assets/l10n/intl_fr.arb +++ b/assets/l10n/intl_fr.arb @@ -1,2379 +1,2741 @@ { - "@@locale": "fr", - "@@last_modified": "2021-08-14 12:41:10.051787", - "about": "À propos", - "@about": { - "type": "text", - "placeholders": {} - }, - "accept": "Accepter", - "@accept": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "👍 {username} a accepté l'invitation", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "Compte", - "@account": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "🔐 {username} a activé le chiffrement de bout en bout", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "addEmail": "Ajouter un courriel", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "addToSpace": "Ajouter à l'espace", - "@addToSpace": {}, - "admin": "Administrateur", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "adresse", - "@alias": { - "type": "text", - "placeholders": {} - }, - "all": "Tout", - "@all": { - "type": "text", - "placeholders": {} - }, - "allChats": "Toutes les discussions", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "{senderName} a répondu à l'appel", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "Tout le monde peut rejoindre", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "appLock": "Verrouillage de l’application", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "archive": "Archiver", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "Les invités peuvent-i·e·ls rejoindre", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "Êtes-vous sûr·e ?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "areYouSureYouWantToLogout": "Voulez-vous vraiment vous déconnecter ?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "Pour pouvoir faire signer l'autre personne, veuillez entrer la phrase de passe de votre trousseau sécurisé ou votre clé de récupération.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "Accepter cette demande de vérification de la part de {username} ?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "autoplayImages": "Lire automatiquement les autocollants et les émojis animés", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "badServerLoginTypesException": "Le serveur d'accueil prend en charge les types de connexion :\n{serverVersions}\nMais cette application ne prend en charge que :\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "badServerVersionsException": "Le serveur d'accueil prend en charge les versions des spécifications :\n{serverVersions}\nMais cette application ne prend en charge que {supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "banFromChat": "Bannir de la discussion", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "Banni", - "@banned": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "{username} a banni {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "blockDevice": "Bloquer l'appareil", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "Bloqué", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "botMessages": "Messages de bot", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "cancel": "Annuler", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "cantOpenUri": "Impossible d'ouvrir l'URI {uri}", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "changeDeviceName": "Modifier le nom de l'appareil", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "{username} a changé l'image de la discussion", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatDescriptionTo": "{username} a changé la description de la discussion en : '{description}'", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheChatNameTo": "{username} a renommé la discussion en : '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheChatPermissions": "{username} a changé les permissions de la discussion", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "{username} a changé son nom en : '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRules": "{username} a changé les règles d'accès à la discussion pour les invités", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} a changé les règles d'accès à la discussion pour les invités en : {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheHistoryVisibility": "{username} a changé la visibilité de l'historique de la discussion", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "{username} a changé la visibilité de l'historique de la discussion en : {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username} a changé les règles d'accès à la discussion", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "{username} a changé les règles d'accès à la discussion en : {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheProfileAvatar": "{username} a changé son avatar", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "{username} a changé les adresses du salon", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomInvitationLink": "{username} a changé le lien d'invitation", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changePassword": "Changer de mot de passe", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "changeTheHomeserver": "Changer le serveur d'accueil", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "Changez votre style", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "Changer le nom du groupe", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "Changer votre avatar", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "Le chiffrement a été corrompu", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chat": "Discussion", - "@chat": { - "type": "text", - "placeholders": {} - }, - "chatBackup": "Sauvegarde des discussions", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "Vos anciens messages sont sécurisés par une clé de récupération. Veillez à ne pas la perdre.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "Détails de la discussion", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "La discussion a été ajoutée à cet espace", - "@chatHasBeenAddedToThisSpace": {}, - "chats": "Discussions", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "Choisissez un mot de passe fort", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "Effacer les archives", - "@clearArchive": {}, - "close": "Fermer", - "@close": { - "type": "text", - "placeholders": {} - }, - "commandHint_ban": "Bannir l'utilisateur/trice donné(e) de ce salon", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_html": "Envoyer du texte au format HTML", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "Inviter l'utilisateur/trice donné(e) dans ce salon", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_join": "Rejoindre le salon donné", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_kick": "Supprime l'utilisateur/trice donné(e) de ce salon", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_leave": "Quitter ce salon", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_me": "Décrivez-vous", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "commandHint_myroomavatar": "Définir votre image pour ce salon (par mxc-uri)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_myroomnick": "Définir votre nom d'affichage pour ce salon", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_op": "Définir le niveau de puissance de l'utilisateur/trice donné(e) (par défaut : 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_plain": "Envoyer du texte non formaté", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_react": "Envoyer une réponse en tant que réaction", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandHint_send": "Envoyer du texte", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandHint_unban": "Débannir l'utilisateur/trice donné(e) de ce salon", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "commandInvalid": "Commande invalide", - "@commandInvalid": { - "type": "text" - }, - "commandMissing": "{command} n'est pas une commande.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "compareEmojiMatch": "Veuillez comparer les émojis", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Veuillez comparer les chiffres", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "configureChat": "Configurer la discussion", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "confirm": "Confirmer", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "connect": "Se connecter", - "@connect": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "Le contact a été invité au groupe", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "Contient un nom d'affichage", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "Contient un nom d'utilisateur·ice", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "Le contenu a été signalé aux administrateurs du serveur", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "Copié dans le presse-papier", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "copy": "Copier", - "@copy": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "Copier dans le presse-papiers", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Impossible de déchiffrer le message : {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "countParticipants": "{count} participant(s)", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "create": "Créer", - "@create": { - "type": "text", - "placeholders": {} - }, - "createdTheChat": "💬 {username} a créé la discussion", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "createNewSpace": "Nouvel espace", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "currentlyActive": "Actif en ce moment", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "Sombre", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "dateWithoutYear": "{day}/{month}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateWithYear": "{day}/{month}/{year}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "deactivateAccountWarning": "Cette opération va désactiver votre compte. Une fois cette action effectuée, aucun retour en arrière n'est possible ! Êtes-vous sûr·e ?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "Niveau d'autorisation par défaut", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "delete": "Supprimer", - "@delete": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "Supprimer le compte", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "Supprimer le message", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "device": "Appareil", - "@device": { - "type": "text", - "placeholders": {} - }, - "deviceId": "Identifiant de l'appareil", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "Appareils", - "@devices": { - "type": "text", - "placeholders": {} - }, - "directChats": "Discussions directes", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "Renommage effectué", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "Télécharger le fichier", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "edit": "Modifier", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "Modifier les serveurs bloqués", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "Changer de nom d'affichage", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "Modifier les adresses du salon", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "Modifier l'avatar du salon", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Cette émoticône existe déjà !", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "Raccourci d'émoticône invalide !", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "Packs d'émoticônes pour le salon", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Paramètre des émoticônes", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "emoteShortcode": "Raccourci de l'émoticône", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Vous devez sélectionner un raccourci d'émoticône et une image !", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "Discussion vide", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "Activer globalement le pack d'émoticônes", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "Activer le chiffrement", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "enableEncryptionWarning": "Vous ne pourrez plus désactiver le chiffrement. Êtes-vous sûr(e) ?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "encrypted": "Chiffré", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "encryption": "Chiffrement", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "encryptionNotEnabled": "Le chiffrement n'est pas activé", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "{senderName} a mis fin à l'appel", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "enterAnEmailAddress": "Saisissez une adresse de courriel", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "enterYourHomeserver": "Renseignez votre serveur d'accueil", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "errorObtainingLocation": "Erreur lors de l'obtention de la localisation : {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "everythingReady": "Tout est prêt !", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "Extrêmement offensant", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "fileName": "Nom du ficher", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "fontSize": "Taille de la police", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "forward": "Transférer", - "@forward": { - "type": "text", - "placeholders": {} - }, - "fromJoining": "À partir de l'entrée dans le salon", - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "fromTheInvitation": "À partir de l'invitation", - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "goToTheNewRoom": "Aller dans le nouveau salon", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "group": "Groupe", - "@group": { - "type": "text", - "placeholders": {} - }, - "groupIsPublic": "Le groupe est public", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "groups": "Groupes", - "@groups": { - "type": "text", - "placeholders": {} - }, - "groupWith": "Groupe avec {displayname}", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "guestsAreForbidden": "Les invités ne peuvent pas rejoindre", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "Les invités peuvent rejoindre", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "hasWithdrawnTheInvitationFor": "{username} a annulé l'invitation de {targetName}", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "help": "Aide", - "@help": { - "type": "text", - "placeholders": {} - }, - "hideRedactedEvents": "Cacher les évènements supprimés", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "Cacher les évènements inconnus", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "howOffensiveIsThisContent": "À quel point ce contenu est-il offensant ?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "id": "Identifiant", - "@id": { - "type": "text", - "placeholders": {} - }, - "identity": "Identité", - "@identity": { - "type": "text", - "placeholders": {} - }, - "ignore": "Ignorer", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "Utilisateur·ices ignoré·es", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "J'ai cliqué sur le lien", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "incorrectPassphraseOrKey": "Phrase de passe ou clé de récupération incorrecte", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "Non offensant", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "Inviter un contact", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "Inviter un contact dans {groupName}", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "invited": "Invité·e", - "@invited": { - "type": "text", - "placeholders": {} - }, - "invitedUser": "📩 {username} a invité {targetName}", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "invitedUsersOnly": "Uniquement les utilisateur·ices invité·es", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "inviteForMe": "Inviter pour moi", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "inviteText": "{username} vous a invité·e sur FluffyChat. \n1. Installez FluffyChat : https://fluffychat.im \n2. Inscrivez-vous ou connectez-vous \n3. Ouvrez le lien d'invitation : {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "isTyping": "est en train d'écrire…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "joinedTheChat": "👋 {username} a rejoint la discussion", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "joinRoom": "Rejoindre le salon", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "kicked": "👞 {username} a expulsé {targetName}", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickedAndBanned": "🙅 {username} a expulsé et banni {targetName}", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickFromChat": "Expulser de la discussion", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "lastActiveAgo": "Vu·e pour la dernière fois : {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "leave": "Partir", - "@leave": { - "type": "text", - "placeholders": {} - }, - "leftTheChat": "A quitté la discussion", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "license": "Licence", - "@license": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "Clair", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "loadCountMoreParticipants": "Charger {count} participant·es de plus", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "loadingPleaseWait": "Chargement… Veuillez patienter.", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "loadMore": "Charger plus…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "locationDisabledNotice": "Les services de localisation sont désactivés. Il est nécessaire de les activer avant de pouvoir partager votre localisation.", - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "locationPermissionDeniedNotice": "L'application n'a pas la permission d'accéder à votre localisation. Merci de l'accorder afin de pouvoir partager votre localisation.", - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "login": "Se connecter", - "@login": { - "type": "text", - "placeholders": {} - }, - "logInTo": "Se connecter à {homeserver}", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "logout": "Se déconnecter", - "@logout": { - "type": "text", - "placeholders": {} - }, - "memberChanges": "Changements de membres", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "mention": "Mentionner", - "@mention": { - "type": "text", - "placeholders": {} - }, - "messages": "Messages", - "@messages": { - "type": "text", - "placeholders": {} - }, - "moderator": "Modérateur·rice", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "muteChat": "Mettre la discussion en sourdine", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "Pour l'instant, vous avez besoin de Pantalaimon pour utiliser le chiffrement de bout en bout.", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "newChat": "Nouvelle discussion", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "💬 Nouveau message dans FluffyChat", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "newVerificationRequest": "Nouvelle demande de vérification !", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "next": "Suivant", - "@next": { - "type": "text", - "placeholders": {} - }, - "no": "Non", - "@no": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "Aucune connexion au serveur", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "noEmotesFound": "Aucune émoticône trouvée. 😕", - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "Vous pouvez activer le chiffrement seulement quand le salon n'est plus accessible au public.", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "noGoogleServicesWarning": "Il semble que vous n'ayez aucun service Google sur votre téléphone. C'est une bonne décision pour votre vie privée ! Pour recevoir des notifications dans FluffyChat, nous vous recommandons d'utiliser https://microg.org/ ou https://unifiedpush.org/.", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "noMatrixServer": "{server1} n'est pas un serveur Matrix, souhaitez-vous utiliser {server2} à la place ?", - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "none": "Aucun", - "@none": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "Vous n'avez pas encore ajouté de moyen pour récupérer votre mot de passe.", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "noPermission": "Aucune permission", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "Aucun salon trouvé…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "notifications": "Notifications", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "notificationsEnabledForThisAccount": "Notifications activées pour ce compte", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "numUsersTyping": "{count} utilisateur·ices écrivent…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "obtainingLocation": "Obtention de la localisation…", - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "offensive": "Offensant", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "offline": "Hors ligne", - "@offline": { - "type": "text", - "placeholders": {} - }, - "ok": "Valider", - "@ok": { - "type": "text", - "placeholders": {} - }, - "online": "En ligne", - "@online": { - "type": "text", - "placeholders": {} - }, - "onlineKeyBackupEnabled": "La sauvegarde en ligne des clés est activée", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "oopsPushError": "Oups ! Une erreur s'est malheureusement produite lors du réglage des notifications.", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "Oups, un problème est survenu…", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "Ouvrez l'application pour lire le message", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "openCamera": "Ouvrir l'appareil photo", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "openInMaps": "Ouvrir dans maps", - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "or": "Ou", - "@or": { - "type": "text", - "placeholders": {} - }, - "participant": "Participant(e)", - "@participant": { - "type": "text", - "placeholders": {} - }, - "passphraseOrKey": "Phrase de passe ou clé de récupération", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "password": "Mot de passe", - "@password": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "Mot de passe oublié", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "Le mot de passe a été modifié", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "passwordRecovery": "Récupération du mot de passe", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "people": "Personnes", - "@people": { - "type": "text", - "placeholders": {} - }, - "pickImage": "Choisir une image", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "pin": "Épingler", - "@pin": { - "type": "text", - "placeholders": {} - }, - "play": "Lire {fileName}", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "pleaseChoose": "Veuillez choisir", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "pleaseChooseAPasscode": "Veuillez choisir un code d’accès", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pleaseClickOnLink": "Veuillez cliquer sur le lien contenu dans le courriel puis continuez.", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "Veuillez saisir 4 chiffres ou laisser vide pour désactiver le verrouillage de l’application.", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "Renseignez votre mot de passe", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "Veuillez saisir votre code PIN", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "Renseignez votre nom d'utilisateur·ice", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "pleaseFollowInstructionsOnWeb": "Veuillez suivre les instructions sur le site et appuyer sur Suivant.", - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "privacy": "Vie privée", - "@privacy": { - "type": "text", - "placeholders": {} - }, - "publicRooms": "Salons publics", - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "pushRules": "Règles de notifications", - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "reason": "Motif", - "@reason": { - "type": "text", - "placeholders": {} - }, - "recording": "Enregistrement", - "@recording": { - "type": "text", - "placeholders": {} - }, - "redactedAnEvent": "{username} a supprimé un évènement", - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "redactMessage": "Supprimer un message", - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "register": "S'inscrire", - "@register": { - "type": "text", - "placeholders": {} - }, - "reject": "Refuser", - "@reject": { - "type": "text", - "placeholders": {} - }, - "rejectedTheInvitation": "{username} a refusé l'invitation", - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "rejoin": "Rejoindre de nouveau", - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "remove": "Supprimer", - "@remove": { - "type": "text", - "placeholders": {} - }, - "removeAllOtherDevices": "Supprimer tous les autres appareils", - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "removedBy": "Supprimé par {username}", - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removeDevice": "Supprimer l'appareil", - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "unbanFromChat": "Débannissement de la discussion", - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "removeYourAvatar": "Supprimer votre avatar", - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "renderRichContent": "Afficher les contenus riches des messages", - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "replaceRoomWithNewerVersion": "Remplacer le salon par une nouvelle version", - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "reply": "Répondre", - "@reply": { - "type": "text", - "placeholders": {} - }, - "reportMessage": "Signaler un message", - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "requestPermission": "Demander la permission", - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "roomHasBeenUpgraded": "Le salon a été mis à niveau", - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "roomVersion": "Version du salon", - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "saveFile": "Enregistrer le fichier", - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "search": "Rechercher", - "@search": { - "type": "text", - "placeholders": {} - }, - "security": "Sécurité", - "@security": { - "type": "text", - "placeholders": {} - }, - "seenByUser": "Vu par {username}", - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "send": "Envoyer", - "@send": { - "type": "text", - "placeholders": {} - }, - "sendAMessage": "Envoyer un message", - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "sendAsText": "Envoyer un texte", - "@sendAsText": { - "type": "text" - }, - "sendAudio": "Envoyer un fichier audio", - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "sendFile": "Envoyer un fichier", - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "sendImage": "Envoyer une image", - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "sendMessages": "Envoyer des messages", - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "sendOriginal": "Envoyer le fichier original", - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "sendSticker": "Envoyer un autocollant", - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "sendVideo": "Envoyer une vidéo", - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "sentAFile": "📁 {username} a envoyé un fichier", - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAnAudio": "🎤 {username} a envoyé un fichier audio", - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAPicture": "🖼️ {username} a envoyé une image", - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentASticker": "😊 {username} a envoyé un autocollant", - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAVideo": "🎥 {username} a envoyé une vidéo", - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentCallInformations": "{senderName} a envoyé des informations sur l'appel", - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "setAsCanonicalAlias": "Définir comme adresse principale", - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "setCustomEmotes": "Définir des émoticônes personnalisées", - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "setInvitationLink": "Créer un lien d'invitation", - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "setPermissionsLevel": "Définir le niveau de permissions", - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "setStatus": "Définir le statut", - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "settings": "Paramètres", - "@settings": { - "type": "text", - "placeholders": {} - }, - "share": "Partager", - "@share": { - "type": "text", - "placeholders": {} - }, - "sharedTheLocation": "{username} a partagé sa position", - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "shareLocation": "Partager la localisation", - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "showPassword": "Afficher le mot de passe", - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "singlesignon": "Authentification unique", - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "skip": "Ignorer", - "@skip": { - "type": "text", - "placeholders": {} - }, - "sourceCode": "Code source", - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "spaceIsPublic": "L'espace est public", - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "spaceName": "Nom de l'espace", - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "startedACall": "{senderName} a démarré un appel", - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "status": "Statut", - "@status": { - "type": "text", - "placeholders": {} - }, - "statusExampleMessage": "Comment allez-vous aujourd'hui ?", - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "submit": "Soumettre", - "@submit": { - "type": "text", - "placeholders": {} - }, - "synchronizingPleaseWait": "Synchronisation... Veuillez patienter.", - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "systemTheme": "Système", - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "theyDontMatch": "Elles ne correspondent pas", - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "theyMatch": "Elles correspondent", - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "title": "FluffyChat", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "toggleFavorite": "Activer/désactiver en favori", - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "toggleMuted": "Activer/désactiver la sourdine", - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "toggleUnread": "Marquer comme lu / non lu", - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "tooManyRequestsWarning": "Trop de requêtes. Veuillez réessayer plus tard !", - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "transferFromAnotherDevice": "Transfert à partir d'un autre appareil", - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "tryToSendAgain": "Retenter l'envoi", - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "unavailable": "Indisponible", - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "unbannedUser": "{username} a annulé le bannissement de {targetName}", - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "unblockDevice": "Retirer le blocage sur l'appareil", - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "unknownDevice": "Appareil inconnu", - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "unknownEncryptionAlgorithm": "Algorithme de chiffrement inconnu", - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "unknownEvent": "Événement de type inconnu : '{type}'", - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "unmuteChat": "Retirer la sourdine de la discussion", - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "unpin": "Désépingler", - "@unpin": { - "type": "text", - "placeholders": {} - }, - "unreadChats": "{unreadCount, plural, =1{1 discussion non lue} other{{unreadCount} discussions non lues}}", - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "userAndOthersAreTyping": "{username} et {count} autres sont en train d'écrire…", - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "userAndUserAreTyping": "{username} et {username2} sont en train d'écrire…", - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "userIsTyping": "{username} est en train d'écrire…", - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "userLeftTheChat": "🚪 {username} a quitté la discussion", - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "username": "Nom d'utilisateur·ice", - "@username": { - "type": "text", - "placeholders": {} - }, - "userSentUnknownEvent": "{username} a envoyé un évènement de type {type}", - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "verified": "Vérifié", - "@verified": { - "type": "text", - "placeholders": {} - }, - "verify": "Vérifier", - "@verify": { - "type": "text", - "placeholders": {} - }, - "verifyStart": "Commencer la vérification", - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "verifySuccess": "La vérification a été effectuée avec succès !", - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "verifyTitle": "Vérification de l'autre compte", - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "videoCall": "Appel vidéo", - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "visibilityOfTheChatHistory": "Visibilité de l'historique de la discussion", - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "visibleForAllParticipants": "Visible pour tous les participant·es", - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "visibleForEveryone": "Visible pour tout le monde", - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "voiceMessage": "Message vocal", - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerAcceptRequest": "En attente de l'acceptation de la demande par le partenaire…", - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerEmoji": "En attente de l'acceptation de l'émoji par le partenaire…", - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerNumbers": "En attente de l'acceptation des nombres par le partenaire…", - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "wallpaper": "Image de fond", - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "warning": "Attention !", - "@warning": { - "type": "text", - "placeholders": {} - }, - "weSentYouAnEmail": "Nous vous avons envoyé un courriel", - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "whoCanPerformWhichAction": "Qui peut faire quelle action", - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "whoIsAllowedToJoinThisGroup": "Qui est autorisé·e à rejoindre ce groupe", - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "whyDoYouWantToReportThis": "Pourquoi voulez-vous le signaler ?", - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "wipeChatBackup": "Effacer la sauvegarde de votre discussion pour créer une nouvelle clé de récupération ?", - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "withTheseAddressesRecoveryDescription": "Grâce à ces adresses, vous pouvez récupérer votre mot de passe si vous en avez besoin.", - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "writeAMessage": "Écrivez un message…", - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "yes": "Oui", - "@yes": { - "type": "text", - "placeholders": {} - }, - "you": "Vous", - "@you": { - "type": "text", - "placeholders": {} - }, - "youAreNoLongerParticipatingInThisChat": "Vous ne participez plus à cette discussion", - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "youHaveBeenBannedFromThisChat": "Vous avez été banni·e de cette discussion", - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "yourPublicKey": "Votre clé publique", - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "scanQrCode": "Scanner un code QR", - "@scanQrCode": {}, - "sendOnEnter": "Envoyer avec Entrée", - "@sendOnEnter": {}, - "homeserver": "Serveur d'accueil", - "@homeserver": {}, - "serverRequiresEmail": "Ce serveur doit valider votre adresse électronique pour l'inscription.", - "@serverRequiresEmail": {}, - "enableMultiAccounts": "(BETA) Activer les comptes multiples sur cet appareil", - "@enableMultiAccounts": {}, - "bundleName": "Nom du groupe", - "@bundleName": {}, - "removeFromBundle": "Retirer de ce groupe", - "@removeFromBundle": {}, - "addToBundle": "Ajouter au groupe", - "@addToBundle": {}, - "editBundlesForAccount": "Modifier les groupes pour ce compte", - "@editBundlesForAccount": {}, - "addAccount": "Ajouter un compte", - "@addAccount": {}, - "oneClientLoggedOut": "Un de vos clients a été déconnecté", - "@oneClientLoggedOut": {}, - "link": "Lien", - "@link": {}, - "yourChatBackupHasBeenSetUp": "Votre sauvegarde de la discussion a été mise en place.", - "@yourChatBackupHasBeenSetUp": {}, - "unverified": "Non vérifié", - "@unverified": {}, - "repeatPassword": "Répétez le mot de passe", - "@repeatPassword": {}, - "messageType": "Type de message", - "@messageType": {}, - "openGallery": "Ouvrir dans la Galerie", - "@openGallery": {}, - "time": "Heure", - "@time": {}, - "sender": "Expéditeur/trice", - "@sender": {}, - "messageInfo": "Informations sur le message", - "@messageInfo": {}, - "removeFromSpace": "Supprimer de l’espace", - "@removeFromSpace": {}, - "addToSpaceDescription": "Sélectionnez un espace pour y ajouter cette discussion.", - "@addToSpaceDescription": {}, - "start": "Commencer", - "@start": {}, - "commandHint_create": "Créer un groupe de discussion vide\nUtilisez --no-encryption pour désactiver le chiffrement", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "commandHint_discardsession": "Abandonner la session", - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "commandHint_clearcache": "Vider le cache", - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "commandHint_dm": "Commencer une discussion directe\nUtilisez --no-encryption pour désactiver le chiffrement", - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "openVideoCamera": "Ouvrir la caméra pour une vidéo", - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "publish": "Publier", - "@publish": {}, - "videoWithSize": "Vidéo ({size})", - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "dismiss": "Rejeter", - "@dismiss": {}, - "markAsRead": "Marquer comme lu", - "@markAsRead": {}, - "reportUser": "Signaler l'utilisateur/trice", - "@reportUser": {}, - "openChat": "Ouvrir la discussion", - "@openChat": {}, - "reactedWith": "{sender} a réagi avec {reaction}", - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "emojis": "Émojis", - "@emojis": {}, - "placeCall": "Passer un appel", - "@placeCall": {}, - "voiceCall": "Appel vocal", - "@voiceCall": {}, - "unsupportedAndroidVersion": "Version d'Android non prise en charge", - "@unsupportedAndroidVersion": {}, - "unsupportedAndroidVersionLong": "Cette fonctionnalité nécessite une nouvelle version d'Android. Veuillez vérifier les mises à jour ou la prise en charge de Lineage OS.", - "@unsupportedAndroidVersionLong": {}, - "pinMessage": "Épingler au salon", - "@pinMessage": {}, - "confirmEventUnpin": "Voulez-vous vraiment désépingler définitivement l'événement ?", - "@confirmEventUnpin": {}, - "videoCallsBetaWarning": "Veuillez noter que les appels vidéo sont actuellement en version bêta. Ils peuvent ne pas fonctionner comme prévu ou ne oas fonctionner du tout sur toutes les plateformes.", - "@videoCallsBetaWarning": {}, - "experimentalVideoCalls": "Appels vidéo expérimentaux", - "@experimentalVideoCalls": {}, - "emailOrUsername": "Courriel ou identifiant", - "@emailOrUsername": {}, - "switchToAccount": "Passer au compte {number}", - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "nextAccount": "Compte suivant", - "@nextAccount": {}, - "previousAccount": "Compte précédent", - "@previousAccount": {}, - "widgetJitsi": "Jitsi Meet", - "@widgetJitsi": {}, - "widgetCustom": "Personnalisé", - "@widgetCustom": {}, - "widgetUrlError": "Ceci n'est pas un lien valide.", - "@widgetUrlError": {}, - "widgetNameError": "Veuillez fournir un nom d'affichage.", - "@widgetNameError": {}, - "errorAddingWidget": "Erreur lors de l'ajout du widget.", - "@errorAddingWidget": {}, - "widgetEtherpad": "Note textuelle", - "@widgetEtherpad": {}, - "addWidget": "Ajouter un widget", - "@addWidget": {}, - "widgetName": "Nom", - "@widgetName": {}, - "widgetVideo": "Vidéo", - "@widgetVideo": {}, - "youRejectedTheInvitation": "Vous avez rejeté l'invitation", - "@youRejectedTheInvitation": {}, - "youJoinedTheChat": "Vous avez rejoint la discussion", - "@youJoinedTheChat": {}, - "youHaveWithdrawnTheInvitationFor": "Vous avez retiré l'invitation pour {user}", - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "youAcceptedTheInvitation": "👍 Vous avez accepté l'invitation", - "@youAcceptedTheInvitation": {}, - "youBannedUser": "Vous avez banni {user}", - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "youInvitedBy": "📩 Vous avez été invité par {user}", - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "youInvitedUser": "📩 Vous avez invité {user}", - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "youKicked": "👞 Vous avez dégagé {user}", - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "youKickedAndBanned": "🙅 Vous avez dégagé et banni {user}", - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "youUnbannedUser": "Vous avez débanni {user}", - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "separateChatTypes": "Séparer les discussions directes et les groupes", - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "users": "Utilisateurs/trices", - "@users": {}, - "storeInAndroidKeystore": "Stocker dans Android KeyStore", - "@storeInAndroidKeystore": {}, - "storeInAppleKeyChain": "Stocker dans Apple KeyChain", - "@storeInAppleKeyChain": {}, - "user": "Utilisateur/trice", - "@user": {}, - "custom": "Personnalisé", - "@custom": {}, - "hydrate": "Restaurer à partir du fichier de sauvegarde", - "@hydrate": {}, - "dehydrateWarning": "Cette action ne peut pas être annulée. Assurez-vous d'enregistrer convenablement le fichier de sauvegarde.", - "@dehydrateWarning": {}, - "dehydrateTorLong": "Pour les utilisateurs/trices de TOR, il est recommandé d'exporter la session avant de fermer la fenêtre.", - "@dehydrateTorLong": {}, - "recoveryKey": "Clé de récupération", - "@recoveryKey": {}, - "recoveryKeyLost": "Clé de récupération perdue ?", - "@recoveryKeyLost": {}, - "indexedDbErrorLong": "Le stockage des messages n'est malheureusement pas activé par défaut en mode privé.\nVeuillez consulter :\n - about:config\n - Définir dom.indexedDB.privateBrowsing.enabled à « vrai ».\nSinon, il n'est pas possible d'exécuter FluffyChat.", - "@indexedDbErrorLong": {}, - "saveKeyManuallyDescription": "Enregistrer cette clé manuellement en déclenchant la boîte de dialogue de partage du système ou le presse-papiers.", - "@saveKeyManuallyDescription": {}, - "storeInSecureStorageDescription": "Stocker la clé de récupération dans un espace sécurisé de cet appareil.", - "@storeInSecureStorageDescription": {}, - "indexedDbErrorTitle": "Problèmes relatifs au mode privé", - "@indexedDbErrorTitle": {}, - "dehydrate": "Exporter la session et effacer l'appareil", - "@dehydrate": {}, - "dehydrateTor": "Utilisateurs/trices de TOR : Exporter la session", - "@dehydrateTor": {}, - "hydrateTor": "Utilisateurs/trices de TOR : Importer une session exportée", - "@hydrateTor": {}, - "hydrateTorLong": "Vous avez exporté votre session la dernière fois sur TOR ? Importez-la rapidement et continuez à discuter.", - "@hydrateTorLong": {}, - "pleaseEnterRecoveryKey": "Veuillez saisir votre clé de récupération :", - "@pleaseEnterRecoveryKey": {}, - "pleaseEnterRecoveryKeyDescription": "Pour déverrouiller vos anciens messages, veuillez entrer votre clé de récupération qui a été générée lors d'une session précédente. Votre clé de récupération n'est PAS votre mot de passe.", - "@pleaseEnterRecoveryKeyDescription": {}, - "unlockOldMessages": "Déverrouiller les anciens messages", - "@unlockOldMessages": {}, - "storeSecurlyOnThisDevice": "Stocker de manière sécurisé sur cet appareil", - "@storeSecurlyOnThisDevice": {}, - "countFiles": "{count} fichiers", - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "noKeyForThisMessage": "Cela peut se produire si le message a été envoyé avant que vous ne vous soyez connecté à votre compte sur cet appareil.\n\nIl est également possible que l'expéditeur ait bloqué votre appareil ou qu'un problème de connexion Internet se soit produit.\n\nÊtes-vous capable de lire le message sur une autre session ? Vous pouvez alors transférer le message à partir de celle-ci ! Allez dans Paramètres > Appareils et assurez-vous que vos appareils se sont vérifiés mutuellement. Lorsque vous ouvrirez le salon la fois suivante et que les deux sessions seront au premier plan, les clés seront transmises automatiquement.\n\nVous ne voulez pas perdre les clés en vous déconnectant ou en changeant d'appareil ? Assurez-vous que vous avez activé la sauvegarde de la discussion dans les paramètres.", - "@noKeyForThisMessage": {}, - "enterRoom": "Entrer dans le salon", - "@enterRoom": {}, - "allSpaces": "Tous les espaces", - "@allSpaces": {}, - "commandHint_markasdm": "Marquer comme salon de messagerie directe", - "@commandHint_markasdm": {}, - "commandHint_markasgroup": "Marquer comme groupe", - "@commandHint_markasgroup": {}, - "confirmMatrixId": "Veuillez confirmer votre identifiant Matrix afin de supprimer votre compte.", - "@confirmMatrixId": {}, - "supposedMxid": "Cela devrait être {mxid}", - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "whyIsThisMessageEncrypted": "Pourquoi ce message est-il illisible ?", - "@whyIsThisMessageEncrypted": {}, - "foregroundServiceRunning": "Cette notification s’affiche lorsque le service au premier plan est en cours d’exécution.", - "@foregroundServiceRunning": {}, - "screenSharingTitle": "Partage d'écran", - "@screenSharingTitle": {}, - "screenSharingDetail": "Vous partagez votre écran dans FuffyChat", - "@screenSharingDetail": {}, - "callingPermissions": "Permissions d'appel", - "@callingPermissions": {}, - "callingAccount": "Compte d'appel", - "@callingAccount": {}, - "callingAccountDetails": "Permet à FluffyChat d'utiliser l'application de numérotation native d'Android.", - "@callingAccountDetails": {}, - "appearOnTop": "Apparaître en haut", - "@appearOnTop": {}, - "appearOnTopDetails": "Permet à l'application d'apparaître en haut de l'écran (non nécessaire si vous avez déjà configuré Fluffychat comme compte d'appel)", - "@appearOnTopDetails": {}, - "otherCallingPermissions": "Microphone, caméra et autres autorisations de FluffyChat", - "@otherCallingPermissions": {}, - "newGroup": "Nouveau groupe", - "@newGroup": {}, - "newSpace": "Nouvel espace", - "@newSpace": {}, - "enterSpace": "Entrer dans l’espace", - "@enterSpace": {}, - "numChats": "{number} discussions", - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "hideUnimportantStateEvents": "Masquer les événements d'état sans importance", - "@hideUnimportantStateEvents": {}, - "doNotShowAgain": "Ne plus afficher", - "@doNotShowAgain": {}, - "commandHint_googly": "Envoyer des yeux écarquillés", - "@commandHint_googly": {}, - "commandHint_cuddle": "Envoyer un câlin", - "@commandHint_cuddle": {}, - "commandHint_hug": "Envoyer une accolade", - "@commandHint_hug": {}, - "googlyEyesContent": "{senderName} vous envoie des yeux écarquillés", - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "cuddleContent": "{senderName} vous fait un câlin", - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "hugContent": "{senderName} vous fait une accolade", - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "wasDirectChatDisplayName": "Discussion vide (était {oldDisplayName})", - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "encryptThisChat": "Chiffrer cette discussion", - "@encryptThisChat": {}, - "sorryThatsNotPossible": "Désolé, ce n'est pas possible", - "@sorryThatsNotPossible": {}, - "deviceKeys": "Clés de l’appareil :", - "@deviceKeys": {}, - "startFirstChat": "Commencez votre première discussion", - "@startFirstChat": {}, - "newSpaceDescription": "Les espaces vous permettent de consolider vos conversations et de construire des communautés privées ou publiques.", - "@newSpaceDescription": {}, - "disableEncryptionWarning": "Pour des raisons de sécurité, vous ne pouvez pas désactiver le chiffrement dans une discussion s'il a été activé avant.", - "@disableEncryptionWarning": {}, - "reopenChat": "Rouvrir la discussion", - "@reopenChat": {}, - "noOtherDevicesFound": "Aucun autre appareil trouvé", - "@noOtherDevicesFound": {}, - "noBackupWarning": "Attention ! Sans l'activation de la sauvegarde de la discussion, vous perdrez l'accès à vos messages chiffrés. Il est fortement recommandé d'activer la sauvegarde de la discussion avant de se déconnecter.", - "@noBackupWarning": {}, - "fileHasBeenSavedAt": "Le fichier a été enregistré dans {path}", - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "fileIsTooBigForServer": "Le serveur signale que le fichier est trop volumineux pour être envoyé.", - "@fileIsTooBigForServer": {}, - "jumpToLastReadMessage": "Aller au dernier message lu", - "@jumpToLastReadMessage": {}, - "readUpToHere": "Lisez jusqu’ici", - "@readUpToHere": {}, - "allRooms": "Toutes les conversations groupées", - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "chatPermissions": "Permissions du salon", - "@chatPermissions": {}, - "importFromZipFile": "Importer depuis un fichier .zip", - "@importFromZipFile": {}, - "inviteContactToGroupQuestion": "Voulez-vous inviter {contact} au salon \"{groupName}\" ?", - "@inviteContactToGroupQuestion": {}, - "importEmojis": "Importer des Emojis", - "@importEmojis": {}, - "notAnImage": "Pas un fichier image", - "@notAnImage": {}, - "chatDescriptionHasBeenChanged": "La description du salon a changé", - "@chatDescriptionHasBeenChanged": {}, - "createGroup": "Créer un groupe", - "@createGroup": {}, - "importNow": "Importer maintenant", - "@importNow": {}, - "@reportErrorDescription": {}, - "@setColorTheme": {}, - "@banUserDescription": {}, - "@removeDevicesDescription": {}, - "@tryAgain": {}, - "@unbanUserDescription": {}, - "@messagesStyle": {}, - "@chatDescription": {}, - "@pushNotificationsNotAvailable": {}, - "@invalidServerName": {}, - "@signInWithPassword": {}, - "@makeAdminDescription": {}, - "@setChatDescription": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@optionalRedactReason": {}, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@redactMessageDescription": {}, - "@invalidInput": {}, - "@report": {}, - "@addChatDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@invitePrivateChat": {}, - "@noChatDescriptionYet": {}, - "@learnMore": {}, - "@roomUpgradeDescription": {}, - "@pleaseEnterANumber": {}, - "@profileNotFound": {}, - "@jump": {}, - "@shareInviteLink": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@replace": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@kickUserDescription": {}, - "@invite": {}, - "@openLinkInBrowser": {} -} \ No newline at end of file + "@@locale": "fr", + "@@last_modified": "2021-08-14 12:41:10.051787", + "about": "À propos", + "@about": { + "type": "text", + "placeholders": {} + }, + "accept": "Accepter", + "@accept": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "👍 {username} a accepté l'invitation", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "account": "Compte", + "@account": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "🔐 {username} a activé le chiffrement de bout en bout", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "addEmail": "Ajouter un courriel", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "addToSpace": "Ajouter à l'espace", + "@addToSpace": {}, + "admin": "Administrateur", + "@admin": { + "type": "text", + "placeholders": {} + }, + "alias": "adresse", + "@alias": { + "type": "text", + "placeholders": {} + }, + "all": "Tout", + "@all": { + "type": "text", + "placeholders": {} + }, + "allChats": "Toutes les discussions", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "{senderName} a répondu à l'appel", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "anyoneCanJoin": "Tout le monde peut rejoindre", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "appLock": "Verrouillage de l’application", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "archive": "Archiver", + "@archive": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "Les invités peuvent-i·e·ls rejoindre", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "Êtes-vous sûr·e ?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "areYouSureYouWantToLogout": "Voulez-vous vraiment vous déconnecter ?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "askSSSSSign": "Pour pouvoir faire signer l'autre personne, veuillez entrer la phrase de passe de votre trousseau sécurisé ou votre clé de récupération.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "Accepter cette demande de vérification de la part de {username} ?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "autoplayImages": "Lire automatiquement les autocollants et les émojis animés", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "badServerLoginTypesException": "Le serveur d'accueil prend en charge les types de connexion :\n{serverVersions}\nMais cette application ne prend en charge que :\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "badServerVersionsException": "Le serveur d'accueil prend en charge les versions des spécifications :\n{serverVersions}\nMais cette application ne prend en charge que {supportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "banFromChat": "Bannir de la discussion", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "banned": "Banni", + "@banned": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "{username} a banni {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "blockDevice": "Bloquer l'appareil", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "blocked": "Bloqué", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "botMessages": "Messages de bot", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "cancel": "Annuler", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "cantOpenUri": "Impossible d'ouvrir l'URI {uri}", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "changeDeviceName": "Modifier le nom de l'appareil", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "changedTheChatAvatar": "{username} a changé l'image de la discussion", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatDescriptionTo": "{username} a changé la description de la discussion en : '{description}'", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "changedTheChatNameTo": "{username} a renommé la discussion en : '{chatname}'", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changedTheChatPermissions": "{username} a changé les permissions de la discussion", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "{username} a changé son nom en : '{displayname}'", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRules": "{username} a changé les règles d'accès à la discussion pour les invités", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheGuestAccessRulesTo": "{username} a changé les règles d'accès à la discussion pour les invités en : {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheHistoryVisibility": "{username} a changé la visibilité de l'historique de la discussion", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibilityTo": "{username} a changé la visibilité de l'historique de la discussion en : {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRules": "{username} a changé les règles d'accès à la discussion", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheJoinRulesTo": "{username} a changé les règles d'accès à la discussion en : {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheProfileAvatar": "{username} a changé son avatar", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "{username} a changé les adresses du salon", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomInvitationLink": "{username} a changé le lien d'invitation", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changePassword": "Changer de mot de passe", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "changeTheHomeserver": "Changer le serveur d'accueil", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "Changez votre style", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "Changer le nom du groupe", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "changeYourAvatar": "Changer votre avatar", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "channelCorruptedDecryptError": "Le chiffrement a été corrompu", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "chat": "Discussion", + "@chat": { + "type": "text", + "placeholders": {} + }, + "chatBackup": "Sauvegarde des discussions", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "chatBackupDescription": "Vos anciens messages sont sécurisés par une clé de récupération. Veillez à ne pas la perdre.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "chatDetails": "Détails de la discussion", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chatHasBeenAddedToThisSpace": "La discussion a été ajoutée à cet espace", + "@chatHasBeenAddedToThisSpace": {}, + "chats": "Discussions", + "@chats": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "Choisissez un mot de passe fort", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "clearArchive": "Effacer les archives", + "@clearArchive": {}, + "close": "Fermer", + "@close": { + "type": "text", + "placeholders": {} + }, + "commandHint_ban": "Bannir l'utilisateur/trice donné(e) de ce salon", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_html": "Envoyer du texte au format HTML", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_invite": "Inviter l'utilisateur/trice donné(e) dans ce salon", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "commandHint_join": "Rejoindre le salon donné", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_kick": "Supprime l'utilisateur/trice donné(e) de ce salon", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_leave": "Quitter ce salon", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_me": "Décrivez-vous", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "commandHint_myroomavatar": "Définir votre image pour ce salon (par mxc-uri)", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_myroomnick": "Définir votre nom d'affichage pour ce salon", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "commandHint_op": "Définir le niveau de puissance de l'utilisateur/trice donné(e) (par défaut : 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_plain": "Envoyer du texte non formaté", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_react": "Envoyer une réponse en tant que réaction", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "commandHint_send": "Envoyer du texte", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "commandHint_unban": "Débannir l'utilisateur/trice donné(e) de ce salon", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "commandInvalid": "Commande invalide", + "@commandInvalid": { + "type": "text" + }, + "commandMissing": "{command} n'est pas une commande.", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "compareEmojiMatch": "Veuillez comparer les émojis", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "Veuillez comparer les chiffres", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "configureChat": "Configurer la discussion", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "confirm": "Confirmer", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "connect": "Se connecter", + "@connect": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "Le contact a été invité au groupe", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "Contient un nom d'affichage", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "containsUserName": "Contient un nom d'utilisateur·ice", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "Le contenu a été signalé aux administrateurs du serveur", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "Copié dans le presse-papier", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "copy": "Copier", + "@copy": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "Copier dans le presse-papiers", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "Impossible de déchiffrer le message : {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "countParticipants": "{count} participant(s)", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "create": "Créer", + "@create": { + "type": "text", + "placeholders": {} + }, + "createdTheChat": "💬 {username} a créé la discussion", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "createNewSpace": "Nouvel espace", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "currentlyActive": "Actif en ce moment", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "Sombre", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "dateWithoutYear": "{day}/{month}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "dateWithYear": "{day}/{month}/{year}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "deactivateAccountWarning": "Cette opération va désactiver votre compte. Une fois cette action effectuée, aucun retour en arrière n'est possible ! Êtes-vous sûr·e ?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "Niveau d'autorisation par défaut", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "delete": "Supprimer", + "@delete": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "Supprimer le compte", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "Supprimer le message", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "device": "Appareil", + "@device": { + "type": "text", + "placeholders": {} + }, + "deviceId": "Identifiant de l'appareil", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "devices": "Appareils", + "@devices": { + "type": "text", + "placeholders": {} + }, + "directChats": "Discussions directes", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "displaynameHasBeenChanged": "Renommage effectué", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "Télécharger le fichier", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "edit": "Modifier", + "@edit": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "Modifier les serveurs bloqués", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "Changer de nom d'affichage", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "Modifier les adresses du salon", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "Modifier l'avatar du salon", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "Cette émoticône existe déjà !", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "emoteInvalid": "Raccourci d'émoticône invalide !", + "@emoteInvalid": { + "type": "text", + "placeholders": {} + }, + "emotePacks": "Packs d'émoticônes pour le salon", + "@emotePacks": { + "type": "text", + "placeholders": {} + }, + "emoteSettings": "Paramètre des émoticônes", + "@emoteSettings": { + "type": "text", + "placeholders": {} + }, + "emoteShortcode": "Raccourci de l'émoticône", + "@emoteShortcode": { + "type": "text", + "placeholders": {} + }, + "emoteWarnNeedToPick": "Vous devez sélectionner un raccourci d'émoticône et une image !", + "@emoteWarnNeedToPick": { + "type": "text", + "placeholders": {} + }, + "emptyChat": "Discussion vide", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "enableEmotesGlobally": "Activer globalement le pack d'émoticônes", + "@enableEmotesGlobally": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "Activer le chiffrement", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "enableEncryptionWarning": "Vous ne pourrez plus désactiver le chiffrement. Êtes-vous sûr(e) ?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "encrypted": "Chiffré", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "encryption": "Chiffrement", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "encryptionNotEnabled": "Le chiffrement n'est pas activé", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "{senderName} a mis fin à l'appel", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "enterAnEmailAddress": "Saisissez une adresse de courriel", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "enterYourHomeserver": "Renseignez votre serveur d'accueil", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "errorObtainingLocation": "Erreur lors de l'obtention de la localisation : {error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "everythingReady": "Tout est prêt !", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "extremeOffensive": "Extrêmement offensant", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "fileName": "Nom du ficher", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "fontSize": "Taille de la police", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "forward": "Transférer", + "@forward": { + "type": "text", + "placeholders": {} + }, + "fromJoining": "À partir de l'entrée dans le salon", + "@fromJoining": { + "type": "text", + "placeholders": {} + }, + "fromTheInvitation": "À partir de l'invitation", + "@fromTheInvitation": { + "type": "text", + "placeholders": {} + }, + "goToTheNewRoom": "Aller dans le nouveau salon", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "group": "Groupe", + "@group": { + "type": "text", + "placeholders": {} + }, + "groupIsPublic": "Le groupe est public", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "groups": "Groupes", + "@groups": { + "type": "text", + "placeholders": {} + }, + "groupWith": "Groupe avec {displayname}", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "guestsAreForbidden": "Les invités ne peuvent pas rejoindre", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "Les invités peuvent rejoindre", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "hasWithdrawnTheInvitationFor": "{username} a annulé l'invitation de {targetName}", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "help": "Aide", + "@help": { + "type": "text", + "placeholders": {} + }, + "hideRedactedEvents": "Cacher les évènements supprimés", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "Cacher les évènements inconnus", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "howOffensiveIsThisContent": "À quel point ce contenu est-il offensant ?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "id": "Identifiant", + "@id": { + "type": "text", + "placeholders": {} + }, + "identity": "Identité", + "@identity": { + "type": "text", + "placeholders": {} + }, + "ignore": "Ignorer", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "Utilisateur·ices ignoré·es", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "J'ai cliqué sur le lien", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "incorrectPassphraseOrKey": "Phrase de passe ou clé de récupération incorrecte", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "Non offensant", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "Inviter un contact", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "Inviter un contact dans {groupName}", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "invited": "Invité·e", + "@invited": { + "type": "text", + "placeholders": {} + }, + "invitedUser": "📩 {username} a invité {targetName}", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "invitedUsersOnly": "Uniquement les utilisateur·ices invité·es", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "inviteForMe": "Inviter pour moi", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "inviteText": "{username} vous a invité·e sur FluffyChat.\n1. Visiter fluffychat.im et installer l'application\n2. Inscrivez-vous ou connectez-vous\n3. Ouvrez le lien d'invitation :\n{link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "isTyping": "est en train d'écrire…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "joinedTheChat": "👋 {username} a rejoint la discussion", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "joinRoom": "Rejoindre le salon", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "kicked": "👞 {username} a expulsé {targetName}", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickedAndBanned": "🙅 {username} a expulsé et banni {targetName}", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickFromChat": "Expulser de la discussion", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "lastActiveAgo": "Vu·e pour la dernière fois : {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "leave": "Partir", + "@leave": { + "type": "text", + "placeholders": {} + }, + "leftTheChat": "A quitté la discussion", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "license": "Licence", + "@license": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "Clair", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "loadCountMoreParticipants": "Charger {count} participant·es de plus", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "loadingPleaseWait": "Chargement… Veuillez patienter.", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "loadMore": "Charger plus…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "locationDisabledNotice": "Les services de localisation sont désactivés. Il est nécessaire de les activer avant de pouvoir partager votre localisation.", + "@locationDisabledNotice": { + "type": "text", + "placeholders": {} + }, + "locationPermissionDeniedNotice": "L'application n'a pas la permission d'accéder à votre localisation. Merci de l'accorder afin de pouvoir partager votre localisation.", + "@locationPermissionDeniedNotice": { + "type": "text", + "placeholders": {} + }, + "login": "Se connecter", + "@login": { + "type": "text", + "placeholders": {} + }, + "logInTo": "Se connecter à {homeserver}", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "logout": "Se déconnecter", + "@logout": { + "type": "text", + "placeholders": {} + }, + "memberChanges": "Changements de membres", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "mention": "Mentionner", + "@mention": { + "type": "text", + "placeholders": {} + }, + "messages": "Messages", + "@messages": { + "type": "text", + "placeholders": {} + }, + "moderator": "Modérateur·rice", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "muteChat": "Mettre la discussion en sourdine", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "Pour l'instant, vous avez besoin de Pantalaimon pour utiliser le chiffrement de bout en bout.", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "newChat": "Nouvelle discussion", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "💬 Nouveau message dans FluffyChat", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "newVerificationRequest": "Nouvelle demande de vérification !", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "next": "Suivant", + "@next": { + "type": "text", + "placeholders": {} + }, + "no": "Non", + "@no": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "Aucune connexion au serveur", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "noEmotesFound": "Aucune émoticône trouvée. 😕", + "@noEmotesFound": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "Vous pouvez activer le chiffrement seulement quand le salon n'est plus accessible au public.", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "noGoogleServicesWarning": "Firebase Cloud Messaging ne semble pas être disponible sur votre appareil. Pour continuer à recevoir des notifications poussées, nous vous recommandons d'installer ntfy. Avec ntfy ou un autre fournisseur Unified Push, vous pouvez recevoir des notifications poussées de manière sécurisée. Vous pouvez télécharger ntfy sur le PlayStore ou sur F-Droid.", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "noMatrixServer": "{server1} n'est pas un serveur Matrix, souhaitez-vous utiliser {server2} à la place ?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "none": "Aucun", + "@none": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "Vous n'avez pas encore ajouté de moyen pour récupérer votre mot de passe.", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "noPermission": "Aucune permission", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "Aucun salon trouvé…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "notifications": "Notifications", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "notificationsEnabledForThisAccount": "Notifications activées pour ce compte", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "numUsersTyping": "{count} utilisateur·ices écrivent…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "obtainingLocation": "Obtention de la localisation…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "offensive": "Offensant", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "offline": "Hors ligne", + "@offline": { + "type": "text", + "placeholders": {} + }, + "ok": "Valider", + "@ok": { + "type": "text", + "placeholders": {} + }, + "online": "En ligne", + "@online": { + "type": "text", + "placeholders": {} + }, + "onlineKeyBackupEnabled": "La sauvegarde en ligne des clés est activée", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "Oups ! Une erreur s'est malheureusement produite lors du réglage des notifications.", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "Oups, un problème est survenu…", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "Ouvrez l'application pour lire le message", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "openCamera": "Ouvrir l'appareil photo", + "@openCamera": { + "type": "text", + "placeholders": {} + }, + "openInMaps": "Ouvrir dans maps", + "@openInMaps": { + "type": "text", + "placeholders": {} + }, + "or": "Ou", + "@or": { + "type": "text", + "placeholders": {} + }, + "participant": "Participant(e)", + "@participant": { + "type": "text", + "placeholders": {} + }, + "passphraseOrKey": "Phrase de passe ou clé de récupération", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "password": "Mot de passe", + "@password": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "Mot de passe oublié", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "Le mot de passe a été modifié", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "passwordRecovery": "Récupération du mot de passe", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "people": "Personnes", + "@people": { + "type": "text", + "placeholders": {} + }, + "pickImage": "Choisir une image", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "pin": "Épingler", + "@pin": { + "type": "text", + "placeholders": {} + }, + "play": "Lire {fileName}", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "pleaseChoose": "Veuillez choisir", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "pleaseChooseAPasscode": "Veuillez choisir un code d’accès", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pleaseClickOnLink": "Veuillez cliquer sur le lien contenu dans le courriel puis continuez.", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "Veuillez saisir 4 chiffres ou laisser vide pour désactiver le verrouillage de l’application.", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "Renseignez votre mot de passe", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "Veuillez saisir votre code PIN", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "Renseignez votre nom d'utilisateur·ice", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "pleaseFollowInstructionsOnWeb": "Veuillez suivre les instructions sur le site et appuyer sur Suivant.", + "@pleaseFollowInstructionsOnWeb": { + "type": "text", + "placeholders": {} + }, + "privacy": "Vie privée", + "@privacy": { + "type": "text", + "placeholders": {} + }, + "publicRooms": "Salons publics", + "@publicRooms": { + "type": "text", + "placeholders": {} + }, + "pushRules": "Règles de notifications", + "@pushRules": { + "type": "text", + "placeholders": {} + }, + "reason": "Motif", + "@reason": { + "type": "text", + "placeholders": {} + }, + "recording": "Enregistrement", + "@recording": { + "type": "text", + "placeholders": {} + }, + "redactedAnEvent": "{username} a supprimé un évènement", + "@redactedAnEvent": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "redactMessage": "Supprimer un message", + "@redactMessage": { + "type": "text", + "placeholders": {} + }, + "register": "S'inscrire", + "@register": { + "type": "text", + "placeholders": {} + }, + "reject": "Refuser", + "@reject": { + "type": "text", + "placeholders": {} + }, + "rejectedTheInvitation": "{username} a refusé l'invitation", + "@rejectedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "rejoin": "Rejoindre de nouveau", + "@rejoin": { + "type": "text", + "placeholders": {} + }, + "remove": "Supprimer", + "@remove": { + "type": "text", + "placeholders": {} + }, + "removeAllOtherDevices": "Supprimer tous les autres appareils", + "@removeAllOtherDevices": { + "type": "text", + "placeholders": {} + }, + "removedBy": "Supprimé par {username}", + "@removedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removeDevice": "Supprimer l'appareil", + "@removeDevice": { + "type": "text", + "placeholders": {} + }, + "unbanFromChat": "Débannissement de la discussion", + "@unbanFromChat": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "Supprimer votre avatar", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "renderRichContent": "Afficher les contenus riches des messages", + "@renderRichContent": { + "type": "text", + "placeholders": {} + }, + "replaceRoomWithNewerVersion": "Remplacer le salon par une nouvelle version", + "@replaceRoomWithNewerVersion": { + "type": "text", + "placeholders": {} + }, + "reply": "Répondre", + "@reply": { + "type": "text", + "placeholders": {} + }, + "reportMessage": "Signaler un message", + "@reportMessage": { + "type": "text", + "placeholders": {} + }, + "requestPermission": "Demander la permission", + "@requestPermission": { + "type": "text", + "placeholders": {} + }, + "roomHasBeenUpgraded": "Le salon a été mis à niveau", + "@roomHasBeenUpgraded": { + "type": "text", + "placeholders": {} + }, + "roomVersion": "Version du salon", + "@roomVersion": { + "type": "text", + "placeholders": {} + }, + "saveFile": "Enregistrer le fichier", + "@saveFile": { + "type": "text", + "placeholders": {} + }, + "search": "Rechercher", + "@search": { + "type": "text", + "placeholders": {} + }, + "security": "Sécurité", + "@security": { + "type": "text", + "placeholders": {} + }, + "seenByUser": "Vu par {username}", + "@seenByUser": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "send": "Envoyer", + "@send": { + "type": "text", + "placeholders": {} + }, + "sendAMessage": "Envoyer un message", + "@sendAMessage": { + "type": "text", + "placeholders": {} + }, + "sendAsText": "Envoyer un texte", + "@sendAsText": { + "type": "text" + }, + "sendAudio": "Envoyer un fichier audio", + "@sendAudio": { + "type": "text", + "placeholders": {} + }, + "sendFile": "Envoyer un fichier", + "@sendFile": { + "type": "text", + "placeholders": {} + }, + "sendImage": "Envoyer une image", + "@sendImage": { + "type": "text", + "placeholders": {} + }, + "sendMessages": "Envoyer des messages", + "@sendMessages": { + "type": "text", + "placeholders": {} + }, + "sendOriginal": "Envoyer le fichier original", + "@sendOriginal": { + "type": "text", + "placeholders": {} + }, + "sendSticker": "Envoyer un autocollant", + "@sendSticker": { + "type": "text", + "placeholders": {} + }, + "sendVideo": "Envoyer une vidéo", + "@sendVideo": { + "type": "text", + "placeholders": {} + }, + "sentAFile": "📁 {username} a envoyé un fichier", + "@sentAFile": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAnAudio": "🎤 {username} a envoyé un fichier audio", + "@sentAnAudio": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAPicture": "🖼️ {username} a envoyé une image", + "@sentAPicture": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentASticker": "😊 {username} a envoyé un autocollant", + "@sentASticker": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAVideo": "🎥 {username} a envoyé une vidéo", + "@sentAVideo": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentCallInformations": "{senderName} a envoyé des informations sur l'appel", + "@sentCallInformations": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "setAsCanonicalAlias": "Définir comme adresse principale", + "@setAsCanonicalAlias": { + "type": "text", + "placeholders": {} + }, + "setCustomEmotes": "Définir des émoticônes personnalisées", + "@setCustomEmotes": { + "type": "text", + "placeholders": {} + }, + "setInvitationLink": "Créer un lien d'invitation", + "@setInvitationLink": { + "type": "text", + "placeholders": {} + }, + "setPermissionsLevel": "Définir le niveau de permissions", + "@setPermissionsLevel": { + "type": "text", + "placeholders": {} + }, + "setStatus": "Définir le statut", + "@setStatus": { + "type": "text", + "placeholders": {} + }, + "settings": "Paramètres", + "@settings": { + "type": "text", + "placeholders": {} + }, + "share": "Partager", + "@share": { + "type": "text", + "placeholders": {} + }, + "sharedTheLocation": "{username} a partagé sa position", + "@sharedTheLocation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "shareLocation": "Partager la localisation", + "@shareLocation": { + "type": "text", + "placeholders": {} + }, + "showPassword": "Afficher le mot de passe", + "@showPassword": { + "type": "text", + "placeholders": {} + }, + "singlesignon": "Authentification unique", + "@singlesignon": { + "type": "text", + "placeholders": {} + }, + "skip": "Ignorer", + "@skip": { + "type": "text", + "placeholders": {} + }, + "sourceCode": "Code source", + "@sourceCode": { + "type": "text", + "placeholders": {} + }, + "spaceIsPublic": "L'espace est public", + "@spaceIsPublic": { + "type": "text", + "placeholders": {} + }, + "spaceName": "Nom de l'espace", + "@spaceName": { + "type": "text", + "placeholders": {} + }, + "startedACall": "{senderName} a démarré un appel", + "@startedACall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "status": "Statut", + "@status": { + "type": "text", + "placeholders": {} + }, + "statusExampleMessage": "Comment allez-vous aujourd'hui ?", + "@statusExampleMessage": { + "type": "text", + "placeholders": {} + }, + "submit": "Soumettre", + "@submit": { + "type": "text", + "placeholders": {} + }, + "synchronizingPleaseWait": "Synchronisation... Veuillez patienter.", + "@synchronizingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "systemTheme": "Système", + "@systemTheme": { + "type": "text", + "placeholders": {} + }, + "theyDontMatch": "Elles ne correspondent pas", + "@theyDontMatch": { + "type": "text", + "placeholders": {} + }, + "theyMatch": "Elles correspondent", + "@theyMatch": { + "type": "text", + "placeholders": {} + }, + "title": "FluffyChat", + "@title": { + "description": "Title for the application", + "type": "text", + "placeholders": {} + }, + "toggleFavorite": "Activer/désactiver en favori", + "@toggleFavorite": { + "type": "text", + "placeholders": {} + }, + "toggleMuted": "Activer/désactiver la sourdine", + "@toggleMuted": { + "type": "text", + "placeholders": {} + }, + "toggleUnread": "Marquer comme lu / non lu", + "@toggleUnread": { + "type": "text", + "placeholders": {} + }, + "tooManyRequestsWarning": "Trop de requêtes. Veuillez réessayer plus tard !", + "@tooManyRequestsWarning": { + "type": "text", + "placeholders": {} + }, + "transferFromAnotherDevice": "Transfert à partir d'un autre appareil", + "@transferFromAnotherDevice": { + "type": "text", + "placeholders": {} + }, + "tryToSendAgain": "Retenter l'envoi", + "@tryToSendAgain": { + "type": "text", + "placeholders": {} + }, + "unavailable": "Indisponible", + "@unavailable": { + "type": "text", + "placeholders": {} + }, + "unbannedUser": "{username} a annulé le bannissement de {targetName}", + "@unbannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "unblockDevice": "Retirer le blocage sur l'appareil", + "@unblockDevice": { + "type": "text", + "placeholders": {} + }, + "unknownDevice": "Appareil inconnu", + "@unknownDevice": { + "type": "text", + "placeholders": {} + }, + "unknownEncryptionAlgorithm": "Algorithme de chiffrement inconnu", + "@unknownEncryptionAlgorithm": { + "type": "text", + "placeholders": {} + }, + "unknownEvent": "Événement de type inconnu : '{type}'", + "@unknownEvent": { + "type": "text", + "placeholders": { + "type": {} + } + }, + "unmuteChat": "Retirer la sourdine de la discussion", + "@unmuteChat": { + "type": "text", + "placeholders": {} + }, + "unpin": "Désépingler", + "@unpin": { + "type": "text", + "placeholders": {} + }, + "unreadChats": "{unreadCount, plural, =1{1 discussion non lue} other{{unreadCount} discussions non lues}}", + "@unreadChats": { + "type": "text", + "placeholders": { + "unreadCount": {} + } + }, + "userAndOthersAreTyping": "{username} et {count} autres sont en train d'écrire…", + "@userAndOthersAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "count": {} + } + }, + "userAndUserAreTyping": "{username} et {username2} sont en train d'écrire…", + "@userAndUserAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "username2": {} + } + }, + "userIsTyping": "{username} est en train d'écrire…", + "@userIsTyping": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "userLeftTheChat": "🚪 {username} a quitté la discussion", + "@userLeftTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "username": "Nom d'utilisateur·ice", + "@username": { + "type": "text", + "placeholders": {} + }, + "userSentUnknownEvent": "{username} a envoyé un évènement de type {type}", + "@userSentUnknownEvent": { + "type": "text", + "placeholders": { + "username": {}, + "type": {} + } + }, + "verified": "Vérifié", + "@verified": { + "type": "text", + "placeholders": {} + }, + "verify": "Vérifier", + "@verify": { + "type": "text", + "placeholders": {} + }, + "verifyStart": "Commencer la vérification", + "@verifyStart": { + "type": "text", + "placeholders": {} + }, + "verifySuccess": "La vérification a été effectuée avec succès !", + "@verifySuccess": { + "type": "text", + "placeholders": {} + }, + "verifyTitle": "Vérification de l'autre compte", + "@verifyTitle": { + "type": "text", + "placeholders": {} + }, + "videoCall": "Appel vidéo", + "@videoCall": { + "type": "text", + "placeholders": {} + }, + "visibilityOfTheChatHistory": "Visibilité de l'historique de la discussion", + "@visibilityOfTheChatHistory": { + "type": "text", + "placeholders": {} + }, + "visibleForAllParticipants": "Visible pour tous les participant·es", + "@visibleForAllParticipants": { + "type": "text", + "placeholders": {} + }, + "visibleForEveryone": "Visible pour tout le monde", + "@visibleForEveryone": { + "type": "text", + "placeholders": {} + }, + "voiceMessage": "Message vocal", + "@voiceMessage": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerAcceptRequest": "En attente de l'acceptation de la demande par le partenaire…", + "@waitingPartnerAcceptRequest": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerEmoji": "En attente de l'acceptation de l'émoji par le partenaire…", + "@waitingPartnerEmoji": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerNumbers": "En attente de l'acceptation des nombres par le partenaire…", + "@waitingPartnerNumbers": { + "type": "text", + "placeholders": {} + }, + "wallpaper": "Image de fond :", + "@wallpaper": { + "type": "text", + "placeholders": {} + }, + "warning": "Attention !", + "@warning": { + "type": "text", + "placeholders": {} + }, + "weSentYouAnEmail": "Nous vous avons envoyé un courriel", + "@weSentYouAnEmail": { + "type": "text", + "placeholders": {} + }, + "whoCanPerformWhichAction": "Qui peut faire quelle action", + "@whoCanPerformWhichAction": { + "type": "text", + "placeholders": {} + }, + "whoIsAllowedToJoinThisGroup": "Qui est autorisé·e à rejoindre ce groupe", + "@whoIsAllowedToJoinThisGroup": { + "type": "text", + "placeholders": {} + }, + "whyDoYouWantToReportThis": "Pourquoi voulez-vous le signaler ?", + "@whyDoYouWantToReportThis": { + "type": "text", + "placeholders": {} + }, + "wipeChatBackup": "Effacer la sauvegarde de votre discussion pour créer une nouvelle clé de récupération ?", + "@wipeChatBackup": { + "type": "text", + "placeholders": {} + }, + "withTheseAddressesRecoveryDescription": "Grâce à ces adresses, vous pouvez récupérer votre mot de passe si vous en avez besoin.", + "@withTheseAddressesRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "writeAMessage": "Écrivez un message…", + "@writeAMessage": { + "type": "text", + "placeholders": {} + }, + "yes": "Oui", + "@yes": { + "type": "text", + "placeholders": {} + }, + "you": "Vous", + "@you": { + "type": "text", + "placeholders": {} + }, + "youAreNoLongerParticipatingInThisChat": "Vous ne participez plus à cette discussion", + "@youAreNoLongerParticipatingInThisChat": { + "type": "text", + "placeholders": {} + }, + "youHaveBeenBannedFromThisChat": "Vous avez été banni·e de cette discussion", + "@youHaveBeenBannedFromThisChat": { + "type": "text", + "placeholders": {} + }, + "yourPublicKey": "Votre clé publique", + "@yourPublicKey": { + "type": "text", + "placeholders": {} + }, + "scanQrCode": "Scanner un code QR", + "@scanQrCode": {}, + "sendOnEnter": "Envoyer avec Entrée", + "@sendOnEnter": {}, + "homeserver": "Serveur d'accueil", + "@homeserver": {}, + "serverRequiresEmail": "Ce serveur doit valider votre adresse électronique pour l'inscription.", + "@serverRequiresEmail": {}, + "enableMultiAccounts": "(BETA) Activer les comptes multiples sur cet appareil", + "@enableMultiAccounts": {}, + "bundleName": "Nom du groupe", + "@bundleName": {}, + "removeFromBundle": "Retirer de ce groupe", + "@removeFromBundle": {}, + "addToBundle": "Ajouter au groupe", + "@addToBundle": {}, + "editBundlesForAccount": "Modifier les groupes pour ce compte", + "@editBundlesForAccount": {}, + "addAccount": "Ajouter un compte", + "@addAccount": {}, + "oneClientLoggedOut": "Un de vos clients a été déconnecté", + "@oneClientLoggedOut": {}, + "link": "Lien", + "@link": {}, + "yourChatBackupHasBeenSetUp": "Votre sauvegarde de la discussion a été mise en place.", + "@yourChatBackupHasBeenSetUp": {}, + "unverified": "Non vérifié", + "@unverified": {}, + "repeatPassword": "Répétez le mot de passe", + "@repeatPassword": {}, + "messageType": "Type de message", + "@messageType": {}, + "openGallery": "Ouvrir dans la Galerie", + "@openGallery": {}, + "time": "Heure", + "@time": {}, + "sender": "Expéditeur/trice", + "@sender": {}, + "messageInfo": "Informations sur le message", + "@messageInfo": {}, + "removeFromSpace": "Supprimer de l’espace", + "@removeFromSpace": {}, + "addToSpaceDescription": "Sélectionnez un espace pour y ajouter cette discussion.", + "@addToSpaceDescription": {}, + "start": "Commencer", + "@start": {}, + "commandHint_create": "Créer un groupe de discussion vide\nUtilisez --no-encryption pour désactiver le chiffrement", + "@commandHint_create": { + "type": "text", + "description": "Usage hint for the command /create" + }, + "commandHint_discardsession": "Abandonner la session", + "@commandHint_discardsession": { + "type": "text", + "description": "Usage hint for the command /discardsession" + }, + "commandHint_clearcache": "Vider le cache", + "@commandHint_clearcache": { + "type": "text", + "description": "Usage hint for the command /clearcache" + }, + "commandHint_dm": "Commencer une discussion directe\nUtilisez --no-encryption pour désactiver le chiffrement", + "@commandHint_dm": { + "type": "text", + "description": "Usage hint for the command /dm" + }, + "openVideoCamera": "Ouvrir la caméra pour une vidéo", + "@openVideoCamera": { + "type": "text", + "placeholders": {} + }, + "publish": "Publier", + "@publish": {}, + "videoWithSize": "Vidéo ({size})", + "@videoWithSize": { + "type": "text", + "placeholders": { + "size": {} + } + }, + "dismiss": "Rejeter", + "@dismiss": {}, + "markAsRead": "Marquer comme lu", + "@markAsRead": {}, + "reportUser": "Signaler l'utilisateur/trice", + "@reportUser": {}, + "openChat": "Ouvrir la discussion", + "@openChat": {}, + "reactedWith": "{sender} a réagi avec {reaction}", + "@reactedWith": { + "type": "text", + "placeholders": { + "sender": {}, + "reaction": {} + } + }, + "emojis": "Émojis", + "@emojis": {}, + "placeCall": "Passer un appel", + "@placeCall": {}, + "voiceCall": "Appel vocal", + "@voiceCall": {}, + "unsupportedAndroidVersion": "Version d'Android non prise en charge", + "@unsupportedAndroidVersion": {}, + "unsupportedAndroidVersionLong": "Cette fonctionnalité nécessite une nouvelle version d'Android. Veuillez vérifier les mises à jour ou la prise en charge de Lineage OS.", + "@unsupportedAndroidVersionLong": {}, + "pinMessage": "Épingler au salon", + "@pinMessage": {}, + "confirmEventUnpin": "Voulez-vous vraiment désépingler définitivement l'événement ?", + "@confirmEventUnpin": {}, + "videoCallsBetaWarning": "Veuillez noter que les appels vidéo sont actuellement en version bêta. Ils peuvent ne pas fonctionner comme prévu ou ne oas fonctionner du tout sur toutes les plateformes.", + "@videoCallsBetaWarning": {}, + "experimentalVideoCalls": "Appels vidéo expérimentaux", + "@experimentalVideoCalls": {}, + "emailOrUsername": "Courriel ou identifiant", + "@emailOrUsername": {}, + "switchToAccount": "Passer au compte {number}", + "@switchToAccount": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "nextAccount": "Compte suivant", + "@nextAccount": {}, + "previousAccount": "Compte précédent", + "@previousAccount": {}, + "widgetJitsi": "Jitsi Meet", + "@widgetJitsi": {}, + "widgetCustom": "Personnalisé", + "@widgetCustom": {}, + "widgetUrlError": "Ceci n'est pas un lien valide.", + "@widgetUrlError": {}, + "widgetNameError": "Veuillez fournir un nom d'affichage.", + "@widgetNameError": {}, + "errorAddingWidget": "Erreur lors de l'ajout du widget.", + "@errorAddingWidget": {}, + "widgetEtherpad": "Note textuelle", + "@widgetEtherpad": {}, + "addWidget": "Ajouter un widget", + "@addWidget": {}, + "widgetName": "Nom", + "@widgetName": {}, + "widgetVideo": "Vidéo", + "@widgetVideo": {}, + "youRejectedTheInvitation": "Vous avez rejeté l'invitation", + "@youRejectedTheInvitation": {}, + "youJoinedTheChat": "Vous avez rejoint la discussion", + "@youJoinedTheChat": {}, + "youHaveWithdrawnTheInvitationFor": "Vous avez retiré l'invitation pour {user}", + "@youHaveWithdrawnTheInvitationFor": { + "placeholders": { + "user": {} + } + }, + "youAcceptedTheInvitation": "👍 Vous avez accepté l'invitation", + "@youAcceptedTheInvitation": {}, + "youBannedUser": "Vous avez banni {user}", + "@youBannedUser": { + "placeholders": { + "user": {} + } + }, + "youInvitedBy": "📩 Vous avez été invité par {user}", + "@youInvitedBy": { + "placeholders": { + "user": {} + } + }, + "youInvitedUser": "📩 Vous avez invité {user}", + "@youInvitedUser": { + "placeholders": { + "user": {} + } + }, + "youKicked": "👞 Vous avez dégagé {user}", + "@youKicked": { + "placeholders": { + "user": {} + } + }, + "youKickedAndBanned": "🙅 Vous avez dégagé et banni {user}", + "@youKickedAndBanned": { + "placeholders": { + "user": {} + } + }, + "youUnbannedUser": "Vous avez débanni {user}", + "@youUnbannedUser": { + "placeholders": { + "user": {} + } + }, + "separateChatTypes": "Séparer les discussions directes et les groupes", + "@separateChatTypes": { + "type": "text", + "placeholders": {} + }, + "users": "Utilisateurs/trices", + "@users": {}, + "storeInAndroidKeystore": "Stocker dans Android KeyStore", + "@storeInAndroidKeystore": {}, + "storeInAppleKeyChain": "Stocker dans Apple KeyChain", + "@storeInAppleKeyChain": {}, + "user": "Utilisateur/trice", + "@user": {}, + "custom": "Personnalisé", + "@custom": {}, + "hydrate": "Restaurer à partir du fichier de sauvegarde", + "@hydrate": {}, + "dehydrateWarning": "Cette action ne peut pas être annulée. Assurez-vous d'enregistrer convenablement le fichier de sauvegarde.", + "@dehydrateWarning": {}, + "dehydrateTorLong": "Pour les utilisateurs/trices de TOR, il est recommandé d'exporter la session avant de fermer la fenêtre.", + "@dehydrateTorLong": {}, + "recoveryKey": "Clé de récupération", + "@recoveryKey": {}, + "recoveryKeyLost": "Clé de récupération perdue ?", + "@recoveryKeyLost": {}, + "indexedDbErrorLong": "Le stockage des messages n'est malheureusement pas activé par défaut en mode privé.\nVeuillez consulter :\n - about:config\n - Définir dom.indexedDB.privateBrowsing.enabled à « vrai ».\nSinon, il n'est pas possible d'exécuter FluffyChat.", + "@indexedDbErrorLong": {}, + "saveKeyManuallyDescription": "Enregistrer cette clé manuellement en déclenchant la boîte de dialogue de partage du système ou le presse-papiers.", + "@saveKeyManuallyDescription": {}, + "storeInSecureStorageDescription": "Stocker la clé de récupération dans un espace sécurisé de cet appareil.", + "@storeInSecureStorageDescription": {}, + "indexedDbErrorTitle": "Problèmes relatifs au mode privé", + "@indexedDbErrorTitle": {}, + "dehydrate": "Exporter la session et effacer l'appareil", + "@dehydrate": {}, + "dehydrateTor": "Utilisateurs/trices de TOR : Exporter la session", + "@dehydrateTor": {}, + "hydrateTor": "Utilisateurs/trices de TOR : Importer une session exportée", + "@hydrateTor": {}, + "hydrateTorLong": "Vous avez exporté votre session la dernière fois sur TOR ? Importez-la rapidement et continuez à discuter.", + "@hydrateTorLong": {}, + "pleaseEnterRecoveryKey": "Veuillez saisir votre clé de récupération :", + "@pleaseEnterRecoveryKey": {}, + "pleaseEnterRecoveryKeyDescription": "Pour déverrouiller vos anciens messages, veuillez entrer votre clé de récupération qui a été générée lors d'une session précédente. Votre clé de récupération n'est PAS votre mot de passe.", + "@pleaseEnterRecoveryKeyDescription": {}, + "unlockOldMessages": "Déverrouiller les anciens messages", + "@unlockOldMessages": {}, + "storeSecurlyOnThisDevice": "Stocker de manière sécurisé sur cet appareil", + "@storeSecurlyOnThisDevice": {}, + "countFiles": "{count} fichiers", + "@countFiles": { + "placeholders": { + "count": {} + } + }, + "noKeyForThisMessage": "Cela peut se produire si le message a été envoyé avant que vous ne vous soyez connecté à votre compte sur cet appareil.\n\nIl est également possible que l'expéditeur ait bloqué votre appareil ou qu'un problème de connexion Internet se soit produit.\n\nÊtes-vous capable de lire le message sur une autre session ? Vous pouvez alors transférer le message à partir de celle-ci ! Allez dans Paramètres > Appareils et assurez-vous que vos appareils se sont vérifiés mutuellement. Lorsque vous ouvrirez le salon la fois suivante et que les deux sessions seront au premier plan, les clés seront transmises automatiquement.\n\nVous ne voulez pas perdre les clés en vous déconnectant ou en changeant d'appareil ? Assurez-vous que vous avez activé la sauvegarde de la discussion dans les paramètres.", + "@noKeyForThisMessage": {}, + "enterRoom": "Entrer dans le salon", + "@enterRoom": {}, + "allSpaces": "Tous les espaces", + "@allSpaces": {}, + "commandHint_markasdm": "Marquer comme salon de messages directs pour l'identifiant Matrix indiqué", + "@commandHint_markasdm": {}, + "commandHint_markasgroup": "Marquer comme groupe", + "@commandHint_markasgroup": {}, + "confirmMatrixId": "Veuillez confirmer votre identifiant Matrix afin de supprimer votre compte.", + "@confirmMatrixId": {}, + "supposedMxid": "Cela devrait être {mxid}", + "@supposedMxid": { + "type": "text", + "placeholders": { + "mxid": {} + } + }, + "whyIsThisMessageEncrypted": "Pourquoi ce message est-il illisible ?", + "@whyIsThisMessageEncrypted": {}, + "foregroundServiceRunning": "Cette notification s’affiche lorsque le service au premier plan est en cours d’exécution.", + "@foregroundServiceRunning": {}, + "screenSharingTitle": "Partage d'écran", + "@screenSharingTitle": {}, + "screenSharingDetail": "Vous partagez votre écran dans FuffyChat", + "@screenSharingDetail": {}, + "callingPermissions": "Permissions d'appel", + "@callingPermissions": {}, + "callingAccount": "Compte d'appel", + "@callingAccount": {}, + "callingAccountDetails": "Permet à FluffyChat d'utiliser l'application de numérotation native d'Android.", + "@callingAccountDetails": {}, + "appearOnTop": "Apparaître en haut", + "@appearOnTop": {}, + "appearOnTopDetails": "Permet à l'application d'apparaître en haut de l'écran (non nécessaire si vous avez déjà configuré Fluffychat comme compte d'appel)", + "@appearOnTopDetails": {}, + "otherCallingPermissions": "Microphone, caméra et autres autorisations de FluffyChat", + "@otherCallingPermissions": {}, + "newGroup": "Nouveau groupe", + "@newGroup": {}, + "newSpace": "Nouvel espace", + "@newSpace": {}, + "enterSpace": "Entrer dans l’espace", + "@enterSpace": {}, + "numChats": "{number} discussions", + "@numChats": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "hideUnimportantStateEvents": "Masquer les événements d'état sans importance", + "@hideUnimportantStateEvents": {}, + "doNotShowAgain": "Ne plus afficher", + "@doNotShowAgain": {}, + "commandHint_googly": "Envoyer des yeux écarquillés", + "@commandHint_googly": {}, + "commandHint_cuddle": "Envoyer un câlin", + "@commandHint_cuddle": {}, + "commandHint_hug": "Envoyer une accolade", + "@commandHint_hug": {}, + "googlyEyesContent": "{senderName} vous envoie des yeux écarquillés", + "@googlyEyesContent": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "cuddleContent": "{senderName} vous fait un câlin", + "@cuddleContent": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "hugContent": "{senderName} vous fait une accolade", + "@hugContent": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "wasDirectChatDisplayName": "Discussion vide (était {oldDisplayName})", + "@wasDirectChatDisplayName": { + "type": "text", + "placeholders": { + "oldDisplayName": {} + } + }, + "encryptThisChat": "Chiffrer cette discussion", + "@encryptThisChat": {}, + "sorryThatsNotPossible": "Désolé, ce n'est pas possible", + "@sorryThatsNotPossible": {}, + "deviceKeys": "Clés de l’appareil :", + "@deviceKeys": {}, + "startFirstChat": "Commencez votre première discussion", + "@startFirstChat": {}, + "newSpaceDescription": "Les espaces vous permettent de consolider vos conversations et de construire des communautés privées ou publiques.", + "@newSpaceDescription": {}, + "disableEncryptionWarning": "Pour des raisons de sécurité, vous ne pouvez pas désactiver le chiffrement dans une discussion s'il a été activé avant.", + "@disableEncryptionWarning": {}, + "reopenChat": "Rouvrir la discussion", + "@reopenChat": {}, + "noOtherDevicesFound": "Aucun autre appareil trouvé", + "@noOtherDevicesFound": {}, + "noBackupWarning": "Attention ! Sans l'activation de la sauvegarde de la discussion, vous perdrez l'accès à vos messages chiffrés. Il est fortement recommandé d'activer la sauvegarde de la discussion avant de se déconnecter.", + "@noBackupWarning": {}, + "fileHasBeenSavedAt": "Le fichier a été enregistré dans {path}", + "@fileHasBeenSavedAt": { + "type": "text", + "placeholders": { + "path": {} + } + }, + "fileIsTooBigForServer": "Le serveur signale que le fichier est trop volumineux pour être envoyé.", + "@fileIsTooBigForServer": {}, + "jumpToLastReadMessage": "Aller au dernier message lu", + "@jumpToLastReadMessage": {}, + "readUpToHere": "Lisez jusqu’ici", + "@readUpToHere": {}, + "allRooms": "Tous les groupes de discussion", + "@allRooms": { + "type": "text", + "placeholders": {} + }, + "chatPermissions": "Permissions du salon", + "@chatPermissions": {}, + "importFromZipFile": "Importer depuis un fichier .zip", + "@importFromZipFile": {}, + "inviteContactToGroupQuestion": "Voulez-vous inviter {contact} au salon \"{groupName}\" ?", + "@inviteContactToGroupQuestion": {}, + "importEmojis": "Importer des Emojis", + "@importEmojis": {}, + "notAnImage": "Pas un fichier image.", + "@notAnImage": {}, + "chatDescriptionHasBeenChanged": "La description du salon a changé", + "@chatDescriptionHasBeenChanged": {}, + "createGroup": "Créer un groupe", + "@createGroup": {}, + "importNow": "Importer maintenant", + "@importNow": {}, + "tryAgain": "Nouvelle tentative", + "@tryAgain": {}, + "blockedUsers": "Utilisateurs/trices bloqués", + "@blockedUsers": {}, + "redactMessageDescription": "Le message sera modifié pour tous les participants de cette conversation. Il n'est pas possible de revenir en arrière.", + "@redactMessageDescription": {}, + "redactedBy": "Modifié par {username}", + "@redactedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "directChat": "Discussion directe", + "@directChat": {}, + "optionalRedactReason": "(Facultatif) Raison de la modification de ce message...", + "@optionalRedactReason": {}, + "subspace": "Sous-espace", + "@subspace": {}, + "sendTypingNotifications": "Envoyer des notifications de frappe", + "@sendTypingNotifications": {}, + "replace": "Remplacer", + "@replace": {}, + "emoteKeyboardNoRecents": "Les émoticônes récemment utilisées apparaîtront ici...", + "@emoteKeyboardNoRecents": { + "type": "text", + "placeholders": {} + }, + "nothingFound": "Rien n'a été trouvé...", + "@nothingFound": {}, + "chatDescription": "Description de la discussion", + "@chatDescription": {}, + "invalidServerName": "Nom de serveur invalide", + "@invalidServerName": {}, + "addChatDescription": "Ajouter une description à la discussion...", + "@addChatDescription": {}, + "shareInviteLink": "Partager un lien d'invitation", + "@shareInviteLink": {}, + "openLinkInBrowser": "Ouvrir le lien dans le navigateur", + "@openLinkInBrowser": {}, + "setTheme": "Définir le thème :", + "@setTheme": {}, + "setColorTheme": "Définir la couleur du thème :", + "@setColorTheme": {}, + "databaseMigrationBody": "Veuillez patienter. Cela peut prendre un moment.", + "@databaseMigrationBody": {}, + "searchForUsers": "Rechercher des @utilisateurs/trices...", + "@searchForUsers": {}, + "passwordsDoNotMatch": "Les mots de passe ne correspondent pas", + "@passwordsDoNotMatch": {}, + "passwordIsWrong": "Votre mot de passe saisi est erroné", + "@passwordIsWrong": {}, + "publicLink": "Lien public", + "@publicLink": {}, + "joinSpace": "Rejoindre l'espace", + "@joinSpace": {}, + "publicSpaces": "Espaces publics", + "@publicSpaces": {}, + "addChatOrSubSpace": "Ajouter une discussion ou un sous-espace", + "@addChatOrSubSpace": {}, + "thisDevice": "Cet appareil :", + "@thisDevice": {}, + "sendReadReceipts": "Envoyer des accusés de réception", + "@sendReadReceipts": {}, + "sendTypingNotificationsDescription": "Les autres participants à une discussion peuvent voir que vous êtes en train de taper un nouveau message.", + "@sendTypingNotificationsDescription": {}, + "verifyOtherDevice": "🔐 Vérifier l'autre appareil", + "@verifyOtherDevice": {}, + "databaseBuildErrorBody": "La base de données SQlite ne peut pas être créée. L'application essaie d'utiliser la base de données existante pour le moment. Veuillez signaler cette erreur aux développeurs à {url}. Le message d'erreur est le suivant : {error}", + "@databaseBuildErrorBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "startConversation": "Démarrer la conversation", + "@startConversation": {}, + "formattedMessagesDescription": "Affichez le contenu formaté des messages comme du texte en gras à l'aide de markdown.", + "@formattedMessagesDescription": {}, + "incomingMessages": "Messages entrants", + "@incomingMessages": {}, + "acceptedKeyVerification": "{sender} a accepté la vérification de clé", + "@acceptedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "pleaseTryAgainLaterOrChooseDifferentServer": "Veuillez réessayer plus tard ou choisir un autre serveur.", + "@pleaseTryAgainLaterOrChooseDifferentServer": {}, + "inviteGroupChat": "📨 Inviter à une discussion de groupe", + "@inviteGroupChat": {}, + "invitePrivateChat": "📨 Inviter à une discussion privée", + "@invitePrivateChat": {}, + "jump": "Sauter", + "@jump": {}, + "signInWithPassword": "Se connecter avec mot de passe", + "@signInWithPassword": {}, + "hideMemberChangesInPublicChats": "Masquer les modifications de membres dans les discussions publiques", + "@hideMemberChangesInPublicChats": {}, + "hideMemberChangesInPublicChatsBody": "Ne pas afficher dans la chronologie de la discussion si quelqu'un rejoint ou quitte une discussion publique afin d'améliorer la lisibilité.", + "@hideMemberChangesInPublicChatsBody": {}, + "overview": "Aperçu", + "@overview": {}, + "notifyMeFor": "Me notifier pour", + "@notifyMeFor": {}, + "passwordRecoverySettings": "Paramètres de récupération de mot de passe", + "@passwordRecoverySettings": {}, + "hasKnocked": "🚪 {user} a frappé", + "@hasKnocked": { + "placeholders": { + "user": {} + } + }, + "canceledKeyVerification": "{sender} a annulé la vérification de clé", + "@canceledKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "unreadChatsInApp": "{appname} : {unread} discussions non lus", + "@unreadChatsInApp": { + "type": "text", + "placeholders": { + "appname": {}, + "unread": {} + } + }, + "requestedKeyVerification": "{sender} a demandé une vérification de clé", + "@requestedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "startedKeyVerification": "{sender} a lancé la vérification de clé", + "@startedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "discover": "Découvrir", + "@discover": {}, + "usersMustKnock": "Les utilisateurs/trices doivent frapper", + "@usersMustKnock": {}, + "noOneCanJoin": "Personne ne peut rejoindre", + "@noOneCanJoin": {}, + "knock": "Frapper à la porte", + "@knock": {}, + "hidePresences": "Cacher la liste des statuts ?", + "@hidePresences": {}, + "appLockDescription": "Verrouiller l'application avec un code PIN lorsqu'elle n'est pas utilisée", + "@appLockDescription": {}, + "globalChatId": "Identifiant global de la discussion", + "@globalChatId": {}, + "accessAndVisibility": "Accès et visibilité", + "@accessAndVisibility": {}, + "accessAndVisibilityDescription": "Qui est autorisé à rejoindre cette discussion et comment la discussion peut être découverte.", + "@accessAndVisibilityDescription": {}, + "calls": "Appels", + "@calls": {}, + "customEmojisAndStickers": "Émoticônes et autocollants personnalisés", + "@customEmojisAndStickers": {}, + "hideRedactedMessages": "Cacher les messages édités", + "@hideRedactedMessages": {}, + "pleaseEnterYourCurrentPassword": "Veuillez saisir votre mot de passe actuel", + "@pleaseEnterYourCurrentPassword": {}, + "swipeRightToLeftToReply": "Glisser de droite à gauche pour répondre", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "true", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "hideRedactedMessagesBody": "Si quelqu'un modifie un message, celui-ci ne sera plus visible dans la discussion.", + "@hideRedactedMessagesBody": {}, + "customEmojisAndStickersBody": "Ajoutez ou partagez des émoticônes ou autocollants personnalisés qui peuvent être utilisés dans n'importe quelle discussion.", + "@customEmojisAndStickersBody": {}, + "blockListDescription": "Vous pouvez bloquer des utilisateurs/trices qui vous dérangent. Vous ne pourrez plus recevoir aucun message ou invitation à un salon d'utilisateurs/trices figurant sur votre liste de blocage personnelle.", + "@blockListDescription": {}, + "blockUsername": "Ignorer le nom d'utilisateur/trice", + "@blockUsername": {}, + "hideInvalidOrUnknownMessageFormats": "Masquer les formats de message invalides ou inconnus", + "@hideInvalidOrUnknownMessageFormats": {}, + "messagesStyle": "Messages :", + "@messagesStyle": {}, + "redactedByBecause": "Modifié par {username} car : \"{reason}\"", + "@redactedByBecause": { + "type": "text", + "placeholders": { + "username": {}, + "reason": {} + } + }, + "setChatDescription": "Définir la description de la discussion", + "@setChatDescription": {}, + "presenceStyle": "Statut :", + "@presenceStyle": { + "type": "text", + "placeholders": {} + }, + "presencesToggle": "Afficher les messages de statut des autres utilisateurs/trices", + "@presencesToggle": { + "type": "text", + "placeholders": {} + }, + "youInvitedToBy": "📩 Vous avez été invité par lien à :\n{alias}", + "@youInvitedToBy": { + "placeholders": { + "alias": {} + } + }, + "userWouldLikeToChangeTheChat": "{user} souhaite rejoindre la discussion.", + "@userWouldLikeToChangeTheChat": { + "placeholders": { + "user": {} + } + }, + "noPublicLinkHasBeenCreatedYet": "Aucun lien public n'a encore été crée", + "@noPublicLinkHasBeenCreatedYet": {}, + "gallery": "Galerie", + "@gallery": {}, + "files": "Fichiers", + "@files": {}, + "sessionLostBody": "Votre session est perdue. Veuillez signaler cette erreur aux développeurs à {url}. Le message d'erreur est le suivant : {error}", + "@sessionLostBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "searchIn": "Rechercher dans la discussion \"{chat}\"...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "forwardMessageTo": "Transférer le message à {roomName} ?", + "@forwardMessageTo": { + "type": "text", + "placeholders": { + "roomName": {} + } + }, + "sendReadReceiptsDescription": "Les autres participants à une discussion peuvent voir si vous avez lu un message.", + "@sendReadReceiptsDescription": {}, + "formattedMessages": "Messages formatés", + "@formattedMessages": {}, + "verifyOtherUser": "🔐 Vérifier l'autre utilisateur/trice", + "@verifyOtherUser": {}, + "searchMore": "Rechercher davantage...", + "@searchMore": {}, + "verifyOtherUserDescription": "Si vous vérifiez un autre utilisateur/trice, vous pouvez être sûr de savoir à qui vous écrivez réellement. 💪\n\nLorsque vous lancez une vérification, vous et l'autre utilisateur/trice verrez une fenêtre contextuelle dans l'application. Vous y verrez alors une série d'émoticônes ou de chiffres que vous devrez comparer.\n\nLa meilleure façon de procéder est de se rencontrer ou de lancer un appel vidéo. 👭", + "@verifyOtherUserDescription": {}, + "verifyOtherDeviceDescription": "Lorsque vous vérifiez un autre appareil, ces appareils peuvent échanger des clés, ce qui augmente votre sécurité globale. 💪 Lorsque vous lancez une vérification, une fenêtre contextuelle s'affiche dans l'application sur les deux appareils. Vous y verrez alors une série d'émoticônes ou de chiffres que vous devrez comparer. Il est préférable d'avoir les deux appareils à portée de main avant de lancer la vérification. 🤳", + "@verifyOtherDeviceDescription": {}, + "completedKeyVerification": "{sender} a terminé la vérification de clé", + "@completedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "isReadyForKeyVerification": "{sender} est prêt pour la vérification de clé", + "@isReadyForKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "transparent": "Transparent", + "@transparent": {}, + "stickers": "Autocollants", + "@stickers": {}, + "noDatabaseEncryption": "Le chiffrement de la base de données n'est pas supporté sur cette plateforme", + "@noDatabaseEncryption": {}, + "commandHint_ignore": "Ignorer l'identifiant Matrix indiqué", + "@commandHint_ignore": {}, + "commandHint_unignore": "Ne plus ignorer l'identifiant Matrix indiqué", + "@commandHint_unignore": {}, + "thereAreCountUsersBlocked": "Actuellement, il y a {count} utilisateurs/trices bloqués.", + "@thereAreCountUsersBlocked": { + "type": "text", + "count": {} + }, + "restricted": "Limité", + "@restricted": {}, + "knockRestricted": "Frapper à la porte limité", + "@knockRestricted": {}, + "signInWith": "Se connecter avec {provider}", + "@signInWith": { + "type": "text", + "placeholders": { + "provider": {} + } + }, + "groupCanBeFoundViaSearch": "Le groupe peut être trouvé via la recherche", + "@groupCanBeFoundViaSearch": {}, + "groupName": "Nom du groupe", + "@groupName": {}, + "invalidInput": "Entrée invalide !", + "@invalidInput": {}, + "block": "Bloquer", + "@block": {}, + "removeDevicesDescription": "Vous serez déconnecté de cet appareil et ne pourrez plus recevoir de messages.", + "@removeDevicesDescription": {}, + "userRole": "Rôle de l'utilisateur/trice", + "@userRole": {}, + "createNewAddress": "Créer une nouvelle adresse", + "@createNewAddress": {}, + "publicChatAddresses": "Addresses de discussion publiques", + "@publicChatAddresses": {}, + "countChatsAndCountParticipants": "{chats} discussions et {participants} participants", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "space": "Espace", + "@space": {}, + "spaces": "Espaces", + "@spaces": {}, + "noMoreChatsFound": "Aucune autre discussion trouvée...", + "@noMoreChatsFound": {}, + "unread": "Non lu", + "@unread": {}, + "joinedChats": "Discussions rejointes", + "@joinedChats": {}, + "commandHint_sendraw": "Envoyer du JSON brut", + "@commandHint_sendraw": {}, + "databaseMigrationTitle": "La base de données est optimisée", + "@databaseMigrationTitle": {}, + "leaveEmptyToClearStatus": "Laisser vide pour effacer votre statut.", + "@leaveEmptyToClearStatus": {}, + "select": "Sélectionner", + "@select": {}, + "reportErrorDescription": "😭 Oh non. Quelque chose s'est mal passé. Si vous le souhaitez, vous pouvez signaler ce bogue aux développeurs.", + "@reportErrorDescription": {}, + "report": "signaler", + "@report": {}, + "wrongPinEntered": "Mauvais code PIN saisi ! Veuillez réessayer dans {seconds} secondes...", + "@wrongPinEntered": { + "type": "text", + "placeholders": { + "seconds": {} + } + }, + "pushNotificationsNotAvailable": "Notifications poussées indisponibles", + "@pushNotificationsNotAvailable": {}, + "yourGlobalUserIdIs": "Votre identifiant utilisateur global est : ", + "@yourGlobalUserIdIs": {}, + "chatCanBeDiscoveredViaSearchOnServer": "La discussion peut être découverte via la recherche sur {server}", + "@chatCanBeDiscoveredViaSearchOnServer": { + "type": "text", + "placeholders": { + "server": {} + } + }, + "knocking": "Frapper", + "@knocking": {}, + "banUserDescription": "L'utilisateur/trice sera banni de la discussion et ne pourra plus y accéder jusqu'à ce qu'il/elle soit débanni.", + "@banUserDescription": {}, + "unbanUserDescription": "L'utilisateur/trice pourra entrer à nouveau dans la discussion si il/elle le souhaite.", + "@unbanUserDescription": {}, + "kickUserDescription": "L'utilisateur/trice est expulsé de la discussion mais n'est pas banni. Dans les discussions publiques, l'utilisateur/trice peut revenir à tout moment.", + "@kickUserDescription": {}, + "makeAdminDescription": "Une fois que vous aurez nommé cet utilisateur/trice administrateur, vous ne pourrez peut-être plus annuler cette opération, car il disposera alors des mêmes autorisations que vous.", + "@makeAdminDescription": {}, + "newPassword": "Nouveau mot de passe", + "@newPassword": {}, + "pleaseChooseAStrongPassword": "Veuillez choisir un mot de passe fort", + "@pleaseChooseAStrongPassword": {}, + "decline": "Refuser", + "@decline": {}, + "initAppError": "Une erreur est survenue pendant l'initialisation de l'application", + "@initAppError": {}, + "markAsUnread": "Marquer comme non lu", + "@markAsUnread": {}, + "wrongRecoveryKey": "Désolé... il ne semble pas s'agir de la bonne clé de récupération.", + "@wrongRecoveryKey": {}, + "searchChatsRooms": "Rechercher des #discussions, @utilisateurs/trices...", + "@searchChatsRooms": {}, + "createGroupAndInviteUsers": "Créer un groupe et inviter des utilisateurs/trices", + "@createGroupAndInviteUsers": {}, + "goToSpace": "Aller dans l'espace : {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "exportEmotePack": "Exporter le pack d'émoticônes au format .zip", + "@exportEmotePack": {}, + "noChatDescriptionYet": "Aucune description de discussion n'a encore été créée.", + "@noChatDescriptionYet": {}, + "invite": "Inviter", + "@invite": {}, + "pleaseEnterANumber": "Veuillez saisir un nombre supérieur à 0", + "@pleaseEnterANumber": {}, + "roomUpgradeDescription": "La discussion sera alors recréé avec la nouvelle version de salon. Tous les participants seront informés qu'ils doivent passer à la nouvelle discussion. Pour en savoir plus sur les versions des salons, consultez le site https://spec.matrix.org/latest/rooms/", + "@roomUpgradeDescription": {}, + "learnMore": "En savoir plus", + "@learnMore": {}, + "minimumPowerLevel": "{level} est le niveau minimum de droits.", + "@minimumPowerLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "restoreSessionBody": "L'application tente maintenant de restaurer votre session depuis la sauvegarde. Veuillez signaler cette erreur aux développeurs à {url}. Le message d'erreur est le suivant : {error}", + "@restoreSessionBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "profileNotFound": "Cet utilisateur/trice n'a pu être trouvé sur le serveur. Peut-être est-ce un problème de connexion ou l'utilisateur/trice n'existe pas.", + "@profileNotFound": {}, + "archiveRoomDescription": "La discussion sera déplacée dans les archives. Les autres utilisateurs/trices pourront voir que vous avez quitté la discussion.", + "@archiveRoomDescription": {}, + "noUsersFoundWithQuery": "Malheureusement, aucun utilisateur/trice n'a pu être trouvé avec \"{query}\". Veuillez vérifier si vous n'avez pas fait de faute de frappe.", + "@noUsersFoundWithQuery": { + "type": "text", + "placeholders": { + "query": {} + } + } +} diff --git a/assets/l10n/intl_ga.arb b/assets/l10n/intl_ga.arb index c4ba3b5bd..5d01bfef6 100644 --- a/assets/l10n/intl_ga.arb +++ b/assets/l10n/intl_ga.arb @@ -1,2248 +1,1953 @@ { - "you": "Tú", - "@you": { - "type": "text", - "placeholders": {} - }, - "yes": "Tá", - "@yes": { - "type": "text", - "placeholders": {} - }, - "warning": "Rabhadh!", - "@warning": { - "type": "text", - "placeholders": {} - }, - "wallpaper": "Cúlbhrat", - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "verify": "Deimhnigh", - "@verify": { - "type": "text", - "placeholders": {} - }, - "verified": "Deimhnithe", - "@verified": { - "type": "text", - "placeholders": {} - }, - "username": "Ainm úsáideora", - "@username": { - "type": "text", - "placeholders": {} - }, - "unpin": "Bain biorán", - "@unpin": { - "type": "text", - "placeholders": {} - }, - "unavailable": "Níl ar fáil", - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "title": "FluffyChat", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "systemTheme": "Córas", - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "submit": "Cuir isteach", - "@submit": { - "type": "text", - "placeholders": {} - }, - "statusExampleMessage": "Conas atá tú inniu?", - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "status": "Staid", - "@status": { - "type": "text", - "placeholders": {} - }, - "skip": "Léim", - "@skip": { - "type": "text", - "placeholders": {} - }, - "share": "Roinn", - "@share": { - "type": "text", - "placeholders": {} - }, - "settings": "Socruithe", - "@settings": { - "type": "text", - "placeholders": {} - }, - "send": "Seol", - "@send": { - "type": "text", - "placeholders": {} - }, - "security": "Slándáil", - "@security": { - "type": "text", - "placeholders": {} - }, - "search": "Cuardaigh", - "@search": { - "type": "text", - "placeholders": {} - }, - "reply": "Freagair", - "@reply": { - "type": "text", - "placeholders": {} - }, - "remove": "Bain", - "@remove": { - "type": "text", - "placeholders": {} - }, - "rejoin": "Téigh ar ais isteach", - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "reject": "Diúltaigh", - "@reject": { - "type": "text", - "placeholders": {} - }, - "register": "Cláraigh", - "@register": { - "type": "text", - "placeholders": {} - }, - "recording": "Ag Taifeadadh", - "@recording": { - "type": "text", - "placeholders": {} - }, - "reason": "Fáth", - "@reason": { - "type": "text", - "placeholders": {} - }, - "privacy": "Príobháideacht", - "@privacy": { - "type": "text", - "placeholders": {} - }, - "pin": "Biorán", - "@pin": { - "type": "text", - "placeholders": {} - }, - "people": "Daoine", - "@people": { - "type": "text", - "placeholders": {} - }, - "password": "Pasfhocal", - "@password": { - "type": "text", - "placeholders": {} - }, - "participant": "Rannpháirtí", - "@participant": { - "type": "text", - "placeholders": {} - }, - "directChats": "Comhráite Díreacha", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "deviceId": "ID gléis", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "Scrios an teachtaireacht", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "Scrios an cuntas", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "createNewSpace": "Spás nua", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "countParticipants": "{count} rannpháirtithe", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "or": "Nó", - "@or": { - "type": "text", - "placeholders": {} - }, - "online": "Ar líne", - "@online": { - "type": "text", - "placeholders": {} - }, - "ok": "togha", - "@ok": { - "type": "text", - "placeholders": {} - }, - "offline": "As líne", - "@offline": { - "type": "text", - "placeholders": {} - }, - "offensive": "Maslach", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "notifications": "Fógraí", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "none": "Aon cheann", - "@none": { - "type": "text", - "placeholders": {} - }, - "no": "Níl", - "@no": { - "type": "text", - "placeholders": {} - }, - "next": "Ar Aghaidh", - "@next": { - "type": "text", - "placeholders": {} - }, - "moderator": "Modhnóir", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "messages": "Teachtaireachtaí", - "@messages": { - "type": "text", - "placeholders": {} - }, - "mention": "Luaigh", - "@mention": { - "type": "text", - "placeholders": {} - }, - "logout": "Logáil amach", - "@logout": { - "type": "text", - "placeholders": {} - }, - "login": "Logáil isteach", - "@login": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "Solas", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "license": "Ceadúnas", - "@license": { - "type": "text", - "placeholders": {} - }, - "leave": "Fág", - "@leave": { - "type": "text", - "placeholders": {} - }, - "invited": "Le cuireadh", - "@invited": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "Neamhurchóideach", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "ignore": "Tabhair neamhaird ar", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "identity": "Aitheantas", - "@identity": { - "type": "text", - "placeholders": {} - }, - "id": "ID", - "@id": { - "type": "text", - "placeholders": {} - }, - "help": "Cabhair", - "@help": { - "type": "text", - "placeholders": {} - }, - "groups": "Grúpaí", - "@groups": { - "type": "text", - "placeholders": {} - }, - "group": "Grúpa", - "@group": { - "type": "text", - "placeholders": {} - }, - "forward": "Seol ar aghaidh", - "@forward": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "homeserver": "Freastalaí baile", - "@homeserver": {}, - "encryption": "Criptiúchán", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "encrypted": "Criptithe", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "edit": "Cuir in eagar", - "@edit": { - "type": "text", - "placeholders": {} - }, - "devices": "Gléasanna", - "@devices": { - "type": "text", - "placeholders": {} - }, - "device": "Gléas", - "@device": { - "type": "text", - "placeholders": {} - }, - "delete": "Scrios", - "@delete": { - "type": "text", - "placeholders": {} - }, - "dateWithYear": "{day}/{month}/{year}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "dateWithoutYear": "{day}/{month}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "containsUserName": "Coinníonn sé ainm úsáideora", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "configureChat": "Cumraigh comhrá", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "commandInvalid": "Ordú neamhbhailí", - "@commandInvalid": { - "type": "text" - }, - "commandHint_send": "Seol téacs", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandHint_me": "Déan cur síos ort féin", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "clearArchive": "Glan an cartlann", - "@clearArchive": {}, - "chatDetails": "Sonraí comhrá", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chatBackup": "Cúltaca comhrá", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "D'athraigh {username} abhatár an chomhrá", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changeDeviceName": "Athraigh ainm an ghléis", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "cantOpenUri": "Ní féidir an URI {uri} a oscailt", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "cancel": "Cealaigh", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "botMessages": "Teachtaireachtaí bota", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "blocked": "Bactha", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "blockDevice": "Bac Gléas", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "Chuir {username} cosc ar {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "banned": "Coiscthe", - "@banned": { - "type": "text", - "placeholders": {} - }, - "banFromChat": "Toirmisc ón gcomhrá", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "sendOnEnter": "Seol ar iontráil", - "@sendOnEnter": {}, - "archive": "Cartlann", - "@archive": { - "type": "text", - "placeholders": {} - }, - "appLock": "Bac aip", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "anyoneCanJoin": "Is féidir le aon duine dul isteach", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "D'fhreagair {senderName} an glao", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "allChats": "Gach comhrá", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "all": "Gach", - "@all": { - "type": "text", - "placeholders": {} - }, - "alias": "ailias", - "@alias": { - "type": "text", - "placeholders": {} - }, - "admin": "Riarthóir", - "@admin": { - "type": "text", - "placeholders": {} - }, - "addToSpace": "Cuir go spás", - "@addToSpace": {}, - "addEmail": "Cuir ríomhphoist", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "Thosaigh {username} an criptiú ó dheireadh go deireadh", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "Cuntas", - "@account": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "Ghlac {username} leis an cuireadh", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "accept": "Glac", - "@accept": { - "type": "text", - "placeholders": {} - }, - "about": "Faoi", - "@about": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "Glac leis an iarratas fíoraithe seo ó {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "areYouSureYouWantToLogout": "An bhfuil tú cinnte gur mhaith leat logáil amach?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "An bhfuil tú cinnte?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "An bhfuil cead ag aoi-úsáideoirí a bheith páirteach", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "invitedUser": "Thug {username} cuireadh do {targetName}", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "hideRedactedEvents": "Folaigh imeachtaí athdhéanta", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "Is féidir le haíonna páirt a ghlacadh", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "guestsAreForbidden": "Tá cosc ar aíonna", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "groupWith": "Grúpa le {displayname}", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "groupIsPublic": "Tá an grúpa poiblí", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "fromTheInvitation": "Ón gcuireadh", - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "enterYourHomeserver": "Cuir isteach do fhreastalaí baile", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "Gearrchód emote neamhbhailí!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Tá iomaite ann cheana féin!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "Cuir in eagar abhatár an tseomra", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "Cuir ailiasanna an tseomra in eagar", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "Cuir freastalaí blocáilte in eagar", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "Leibhéal ceada réamhshocraithe", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "unblockDevice": "Díbhlocáil Gléas", - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "Tugadh cuireadh don theagmháil a thar isteach sa grúpa", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Déan comparáid idir na huimhreacha seo a leanas agus déan cinnte go bhfuil na huimhreacha seo a leanas ag teacht le huimhreacha an ghléis eile:", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "compareEmojiMatch": "Déan comparáid agus déan cinnte go bhfuil an emoji seo a leanas comhoiriúnach le emoji an ghléis eile:", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "commandMissing": "Ní ordú é {command}.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "commandHint_react": "Seol freagra mar fhreagairt", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandHint_op": "Socraigh leibhéal cumhachta an úsáideora áirithe (réamhshocrú: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_myroomnick": "Socraigh d'ainm taispeána don seomra seo", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_myroomavatar": "Cuir do phictiúr don seomra seo (le mxc-uri)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_kick": "Bain an t-úsáideoir áirithe den seomra seo", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_join": "Téigh isteach sa seomra áirithe", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_ban": "Cuir cosc ar an úsáideoir áirithe ón seomra seo", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_invite": "Cuir cosc ar an úsáideoir áirithe ón seomra seo", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "chooseAStrongPassword": "Roghnaigh pasfhocal láidir", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "Cuireadh comhrá leis an spás seo", - "@chatHasBeenAddedToThisSpace": {}, - "chatBackupDescription": "Tá do chúltaca comhrá daingnithe le heochair slándála. Déan cinnte nach gcaillfidh tú é.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "Truaillíodh an criptiú", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "Athraigh ainm an ghrúpa", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changedTheRoomInvitationLink": "D'athraigh {username} nasc an chuiridh", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "D'athraigh {username} ailiasanna an tseomra", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheProfileAvatar": "D'athraigh {username} a n-abhatár", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "D'athraigh {username} na rialacha ceangail go: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheJoinRules": "D'athraigh {username} na rialacha ceangail", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "D'athraigh {username} infheictheacht na staire go: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheHistoryVisibility": "D'athraigh {username} infheictheacht na staire", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "D'athraigh {username} a n-ainm taispeána go: '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheChatPermissions": "D'athraigh {username} na ceadanna comhrá", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatNameTo": "D'athraigh {username} an t-ainm comhrá go: '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheChatDescriptionTo": "D'athraigh {username} an cur síos comhrá go: '{description}'", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "autoplayImages": "Seinn greamáin agus straoiseog beoite go huathoibríoch", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "createdTheChat": "Rinne {username} an comhrá", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "copyToClipboard": "Cóipeáil ar an ghearrthaisce", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "Cóipeáilte ar an ghearrthaisce", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "Coinníonn sé ainm taispeána", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "commandHint_plain": "Seol téacs neamhfhoirmithe", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_leave": "Fág an seomra seo", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_html": "Seol téacs HTML-formáidithe", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "changeYourAvatar": "Athraigh do abhatár", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "Athraigh do stíl", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheHomeserver": "Athraigh an freastalaí baile", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "voiceMessage": "Glórphost", - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "videoCall": "Físghlao", - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "verifyStart": "Tosaigh Fíorú", - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "unmuteChat": "Neamhciúnaigh comhrá", - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "Folaigh imeachtaí anaithnide", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "unknownDevice": "Gléas anaithnid", - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "toggleUnread": "Marcáil Léite/Neamhléite", - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "toggleMuted": "Scoránaigh mar ciúnaithe", - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "toggleFavorite": "Scoránaigh mar ceann is fearr leat", - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "theyMatch": "Tá siad céanna", - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "spaceName": "Ainm an spáis", - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "sourceCode": "Cód foinseach", - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "showPassword": "Taispeáin pasfhocal", - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "shareLocation": "Roinn suíomh", - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "setStatus": "Cuir stádas", - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "sendVideo": "Seol físeán", - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "sendSticker": "Seol greamán", - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "sendOriginal": "Seol an bunchóip", - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "sendMessages": "Seol teachtaireachtaí", - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "sendImage": "Seol íomhá", - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "sendFile": "Seol comhad", - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "sendAudio": "Seol fuaim", - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "saveFile": "Sábháil comhad", - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "roomVersion": "Leagan seomra", - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "requestPermission": "Iarr cead", - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "reportMessage": "Tuairiscigh teachtaireacht", - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "removeDevice": "Bain gléas", - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "redactMessage": "Bain teachtaireacht amach", - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "pushRules": "Rialacha na bhfógraí", - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "publicRooms": "Seomraí Poiblí", - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "pleaseChoose": "Roghnaigh le do thoil", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "play": "Seinn {fileName}", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "passwordRecovery": "Aisfháil pasfhocail", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "Pasfhocal dearmadta", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "openCamera": "Oscail ceamara", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "obtainingLocation": "ag Aimsiú an suíomh…", - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "noPermission": "Gan cead", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "newChat": "Comhrá nua", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "muteChat": "Ciúnaigh comhrá", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "memberChanges": "Athruithe ball", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "loadMore": "Lódáil níos mó…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "joinRoom": "Téigh isteach sa seomra", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "isTyping": "ag clóscríobh…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "Tabhair cuireadh do theagmháil", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "Úsáideoirí a dtugann tú neamhaird orthu", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "fromJoining": "Ó tar isteach", - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "fontSize": "Méid cló", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "Tosaigh criptiú", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "Cuir ainm taispeána in eagar", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "currentlyActive": "Gníomhach faoi láthair", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "fileName": "Ainm an chomhaid", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "everythingReady": "Gach rud réidh!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "Comhrá folamh", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "emoteShortcode": "Gearrchód straoiseoige", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Socruithe straoiseoige", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "Íoslódáil comhad", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "changePassword": "Athraigh an pasfhocal", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "Dorcha", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "create": "Cruthaigh", - "@create": { - "type": "text", - "placeholders": {} - }, - "copy": "Cóipeáil", - "@copy": { - "type": "text", - "placeholders": {} - }, - "connect": "Ceangail", - "@connect": { - "type": "text", - "placeholders": {} - }, - "confirm": "Deimhnigh", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "close": "Dún", - "@close": { - "type": "text", - "placeholders": {} - }, - "chats": "Comhráite", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chat": "Comhrá", - "@chat": { - "type": "text", - "placeholders": {} - }, - "scanQrCode": "Scan cód QR", - "@scanQrCode": {}, - "inviteText": "Thug {username} cuireadh duit chuig FluffyChat.\n1. Suiteáil FluffyChat: https://fluffychat.im\n2. Cláraigh nó sínigh isteach\n3. Oscail an nasc cuiridh: {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "noMatrixServer": "Níl {server1} freastalaí Matrix. Úsáid {server2} ina áit sin?", - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "noGoogleServicesWarning": "Dealraíonn sé nach bhfuil aon seirbhísí google agat ar do ghuthán. Sin cinneadh maith le do phríobháideacht! Chun fógraí brú a fháil i FluffyChat molaimid https://microg.org/ nó https://unifiedpush.org/ a úsáid.", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "Ní féidir leat criptiú a ghníomhachtú ach a luaithe nach bhfuil an seomra inrochtana go poiblí a thuilleadh.", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "noEmotesFound": "Níor aimsíodh aon straoiseoga. 😕", - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "Gan aon nasc leis an bhfreastalaí", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "newVerificationRequest": "Iarratas fíoraithe nua!", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "Teachtaireacht nua i FluffyChat", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "Bí ar an eolas go dteastaíonn Pantalaimon uait chun criptiú ó cheann go ceann a úsáid anois.", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "logInTo": "Logáil isteach chuig {homeserver}", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "locationPermissionDeniedNotice": "Diúltaíodh cead suímh. Deonaigh dóibh le do thoil go mbeidh tú in ann do shuíomh a roinnt.", - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "locationDisabledNotice": "Tá seirbhísí suímh díchumasaithe. Cuir ar a gcumas le do thoil a bheith in ann do shuíomh a roinnt.", - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "loadingPleaseWait": "Ag lódáil… Fan, le do thoil.", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "loadCountMoreParticipants": "Lódáil {count} níos mó rannpháirtithe", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "leftTheChat": "Fágadh an comhrá", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "lastActiveAgo": "Gníomhach deireanach: {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "kickFromChat": "Caith é amach as an comhrá", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "kicked": "Chaith {username} {targetName} amach", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickedAndBanned": "Chaith {username} amach agus chuir cosc ar {targetName} freisin", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "joinedTheChat": "Tháinig {username} isteach sa chomhrá", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "invitedUsersOnly": "Úsáideoirí le cuireadh amháin", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "Tabhair cuireadh do theagmháil chuig {groupName}", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "incorrectPassphraseOrKey": "Pasfhrása nó eochair téarnaimh mícheart", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "Chliceáil mé ar an nasc", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "howOffensiveIsThisContent": "Cé chomh maslach atá an t-ábhar seo?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "Fíor-maslach", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "hasWithdrawnTheInvitationFor": "Tharraing {username} an cuireadh do {targetName} siar", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "goToTheNewRoom": "Téigh go dtí an seomra nua", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "errorObtainingLocation": "Earráid maidir le suíomh a fháil: {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "enterAnEmailAddress": "Cuir isteach seoladh ríomhphoist", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "Chuir {senderName} deireadh leis an nglao", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "encryptionNotEnabled": "Ní chumasaítear criptiú", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "enableEncryptionWarning": "Ní bheidh in ann an criptiú a dhíchumasú níos mó. An bhfuil tú cinnte?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "Cumasaigh pacáiste straoiseoige go huilíoch", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Caithfidh tú gearrchód straoiseoige agus íomhá a roghnú!", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "Pacáistí straoiseoige don seomra", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "Athraíodh an t-ainm taispeána", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "deactivateAccountWarning": "Díghníomhachtaeoidh sé seo do chuntas úsáideora. Ní féidir é seo a chealú! An bhfuil tú cinnte?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Níorbh fhéidir teachtaireacht a dhíchriptiú: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "contentHasBeenReported": "Tuairiscíodh an t-ábhar do lucht riaracháin an fhreastalaí", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "commandHint_unban": "Cuir deireadh an cosc den úsáideoir áirithe ón seomra seo", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "changedTheGuestAccessRulesTo": "D'athraigh {username} na rialacha maidir le rochtain aoi chuig: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheGuestAccessRules": "D'athraigh {username} na rialacha rochtana aoi", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "badServerVersionsException": "Tá na leaganacha sonraíochta seo ar fáil faoin freastalaí baile:\n{serverVersions}\nAch níl ach na ceann seo ar fáil faoin aip seo {supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "badServerLoginTypesException": "Tá na cineálacha logála isteach seo ar fáil faoin freastalaí baile:\n{serverVersions}\nAch níl ach na ceann seo ar fáil faoin aip seo:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "askSSSSSign": "Chun a bheith in ann an duine eile a shíniú, cuir isteach do phasfhrása stóir sábháilte nó d'eochair téarnaimh.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "yourPublicKey": "D'eochair phoiblí", - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "youHaveBeenBannedFromThisChat": "Cuireadh cosc ort ón gcomhrá seo", - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "youAreNoLongerParticipatingInThisChat": "Níl tú ag glacadh páirte sa chomhrá seo a thuilleadh", - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "writeAMessage": "Scríobh teachtaireacht…", - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "withTheseAddressesRecoveryDescription": "Leis na seoltaí seo is féidir leat do phasfhocal a athshlánú.", - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "wipeChatBackup": "Glan do cúltaca comhrá a chruthú eochair slándála nua?", - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "whyDoYouWantToReportThis": "Cén fáth ar mhaith leat é seo a thuairisciú?", - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "whoIsAllowedToJoinThisGroup": "Cé a bhfuil cead aige/aici dul isteach sa ghrúpa seo", - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "whoCanPerformWhichAction": "Cé atá in ann an gníomh a dhéanamh", - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "verifySuccess": "D'fhíoraigh tú go rathúil!", - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "userLeftTheChat": "D'fhág {username} an comhrá", - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "userAndUserAreTyping": "Tá {username} agus {username2} ag clóscríobh…", - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "userAndOthersAreTyping": "tá {username} agus {count} daoine eile ag clóscríobh…", - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "unreadChats": "{unreadCount, plural, =1{1 comhrá neamhléite} other{{unreadCount} comhráite neamhléite}}", - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "unknownEncryptionAlgorithm": "Algartam criptithe anaithnid", - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "unbannedUser": "Chuir {username} deireadh an cosc {targetName}", - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "tryToSendAgain": "Déan iarracht a sheoladh arís", - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "transferFromAnotherDevice": "Aistriú ó ghléas eile", - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "tooManyRequestsWarning": "An iomarca iarratas. Bain triail eile as níos déanaí!", - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "theyDontMatch": "Níl siad céanna", - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "sharedTheLocation": "Roinn {username} an suíomh", - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "setPermissionsLevel": "Socraigh leibhéal ceadanna", - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "setInvitationLink": "Socraigh nasc cuiridh", - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "setCustomEmotes": "Socraigh straoiseoga saincheaptha", - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "setAsCanonicalAlias": "Socraigh mar phríomh-ailias", - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "sentCallInformations": "Sheol {senderName} faisnéis maidir le glaonna", - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "sentAVideo": "Sheol {username} físeán", - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentASticker": "Sheol {username} greamán", - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAPicture": "Sheol {username} pictiúr", - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "replaceRoomWithNewerVersion": "Cuir leagan seomra níos nuaí in ionad an tseomra", - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "renderRichContent": "Taispeáin ábhar teachtaireachta saibhir", - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "removeYourAvatar": "Bain d'abhatár", - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "unbanFromChat": "Cuir deireadh an cosc ón gcomhrá", - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "removedBy": "Bainte de ag {username}", - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removeAllOtherDevices": "Bain gach gléas eile", - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "rejectedTheInvitation": "Dhiúltaigh {username} don chuireadh", - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "redactedAnEvent": "Rinne {username} cinsire imeacht", - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "pleaseFollowInstructionsOnWeb": "Lean na treoracha ar an suíomh gréasáin agus tapáil \"ar aghaidh\".", - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "Cuir isteach d'ainm úsáideora le do thoil", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "Cuir isteach d'uimhir PIN le do thoil", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "Iontráil do phasfhocal le do thoil", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "Iontráil 4 dhigit le do thoil nó fág folamh chun glas aipe a dhíchumasú.", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "pleaseClickOnLink": "Cliceáil ar an nasc sa ríomhphost agus ansin lean ar aghaidh.", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "pleaseChooseAPasscode": "Roghnaigh paschód le do thoil", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pickImage": "Roghnaigh íomhá", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "Athraíodh an pasfhocal", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "passphraseOrKey": "pasfhrása nó eochair téarnaimh", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "serverRequiresEmail": "Ní mór don fhreastalaí seo do sheoladh ríomhphoist a bhailíochtú le haghaidh clárúcháin.", - "@serverRequiresEmail": {}, - "openInMaps": "Oscail i léarscáileanna", - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "Oscail an aip chun teachtaireachtaí a léamh", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "Úps, chuaigh rud éigin mícheart …", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "oopsPushError": "Hoips! Ar an drochuair, tharla earráid nuair a bhí na fógraí brú á mbunú.", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "onlineKeyBackupEnabled": "Tá Cúltaca Eochair Ar Líne cumasaithe", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "numUsersTyping": "Tá {count} úsáideoirí ag clóscríobh…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "notificationsEnabledForThisAccount": "Fógraí cumasaithe don chuntas seo", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "Níor aimsíodh aon seomraí…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "Níor chuir tú bealach leis do phasfhocal a aisghabháil fós.", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "inviteForMe": "Tabhair cuireadh dom", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "weSentYouAnEmail": "Sheolamar ríomhphost chugat", - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerNumbers": "Ag fanacht le comhpháirtí glacadh leis na huimhreacha …", - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerEmoji": "Ag fanacht le comhpháirtí glacadh leis na straoiseoga…", - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerAcceptRequest": "Ag fanacht le comhpháirtí glacadh leis an iarratas…", - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "visibleForEveryone": "Infheicthe do gach duine", - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "visibleForAllParticipants": "Infheicthe do na rannpháirtithe go léir", - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "visibilityOfTheChatHistory": "Infheictheacht stair na comhrá", - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "verifyTitle": "Ag fíorú cuntas eile", - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "userSentUnknownEvent": "Sheol {username} imeacht {type}", - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "userIsTyping": "Tá {username} ag clóscríobh…", - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "unknownEvent": "Imeacht anaithnid '{type}'", - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "synchronizingPleaseWait": "Ag sioncrónú... Fan, le do thoil.", - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "startedACall": "Thosaigh {senderName} glao", - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "spaceIsPublic": "Tá an spás poiblí", - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "singlesignon": "Sínigh Aonair ar", - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "sentAnAudio": "Sheol {username} fuaim", - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAFile": "Sheol {username} comhad", - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sendAsText": "Seol mar théacs", - "@sendAsText": { - "type": "text" - }, - "sendAMessage": "Seol teachtaireacht", - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "seenByUser": "Le feiceáil ag {username}", - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "roomHasBeenUpgraded": "Uasghrádaíodh an seomra", - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "addAccount": "Breisigh cuntas", - "@addAccount": {}, - "enableMultiAccounts": "(BÉITE) Cumasaigh cuntais iomadúla ar an gléas seo", - "@enableMultiAccounts": {}, - "commandHint_create": "Cruthaigh comhrá grúpa folamh\nÚsáid --no-encryption chun criptiúchán a dhíchumasú", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "link": "Nasc", - "@link": {}, - "commandHint_clearcache": "Glan an taisce", - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "videoCallsBetaWarning": "Tabhair faoi deara go bhfuil físglaonna i béite. B'fhéidir nach bhfeidhmíonn siad ar gach ardán chomh atá súil aige ná ar bith.", - "@videoCallsBetaWarning": {}, - "emailOrUsername": "Ríomhphost nó ainm úsáideora", - "@emailOrUsername": {}, - "repeatPassword": "Scríobh an pasfhocal arís", - "@repeatPassword": {}, - "yourChatBackupHasBeenSetUp": "Bunaíodh do chúltaca comhrá.", - "@yourChatBackupHasBeenSetUp": {}, - "openVideoCamera": "Oscail físcheamara", - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@widgetVideo": {}, - "@dismiss": {}, - "@reportErrorDescription": {}, - "@unsupportedAndroidVersion": {}, - "@widgetJitsi": {}, - "@messageType": {}, - "@indexedDbErrorLong": {}, - "@oneClientLoggedOut": {}, - "@startFirstChat": {}, - "@callingAccount": {}, - "@setColorTheme": {}, - "@nextAccount": {}, - "@allSpaces": {}, - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "@user": {}, - "@youAcceptedTheInvitation": {}, - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "@banUserDescription": {}, - "@widgetEtherpad": {}, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "@unbanUserDescription": {}, - "@youRejectedTheInvitation": {}, - "@otherCallingPermissions": {}, - "@messagesStyle": {}, - "@widgetUrlError": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@enterSpace": {}, - "@encryptThisChat": {}, - "@previousAccount": {}, - "@reopenChat": {}, - "@pleaseEnterRecoveryKey": {}, - "@widgetNameError": {}, - "@addToBundle": {}, - "@addWidget": {}, - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "@noKeyForThisMessage": {}, - "@commandHint_markasgroup": {}, - "@hydrateTor": {}, - "@pushNotificationsNotAvailable": {}, - "@storeInAppleKeyChain": {}, - "@hydrate": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@sender": {}, - "@storeInAndroidKeystore": {}, - "@signInWithPassword": {}, - "@makeAdminDescription": {}, - "@saveKeyManuallyDescription": {}, - "@editBundlesForAccount": {}, - "@whyIsThisMessageEncrypted": {}, - "@setChatDescription": {}, - "@importFromZipFile": {}, - "@dehydrateWarning": {}, - "@noOtherDevicesFound": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@fileIsTooBigForServer": {}, - "@callingPermissions": {}, - "@readUpToHere": {}, - "@start": {}, - "@unlockOldMessages": {}, - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@optionalRedactReason": {}, - "@dehydrate": {}, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@experimentalVideoCalls": {}, - "@pleaseEnterRecoveryKeyDescription": {}, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "@appearOnTopDetails": {}, - "@enterRoom": {}, - "@reportUser": {}, - "@confirmEventUnpin": {}, - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@redactMessageDescription": {}, - "@recoveryKey": {}, - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "@invalidInput": {}, - "@dehydrateTorLong": {}, - "@doNotShowAgain": {}, - "@report": {}, - "@unverified": {}, - "@hideUnimportantStateEvents": {}, - "@screenSharingTitle": {}, - "@widgetCustom": {}, - "@addToSpaceDescription": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "@addChatDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@publish": {}, - "@openLinkInBrowser": {}, - "@messageInfo": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@foregroundServiceRunning": {}, - "@voiceCall": {}, - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "@noChatDescriptionYet": {}, - "@removeFromBundle": {}, - "@confirmMatrixId": {}, - "@learnMore": {}, - "@notAnImage": {}, - "@users": {}, - "@openGallery": {}, - "@chatDescriptionHasBeenChanged": {}, - "@newGroup": {}, - "@bundleName": {}, - "@dehydrateTor": {}, - "@removeFromSpace": {}, - "@roomUpgradeDescription": {}, - "@pleaseEnterANumber": {}, - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "@profileNotFound": {}, - "@jump": {}, - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "@sorryThatsNotPossible": {}, - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "@shareInviteLink": {}, - "@commandHint_markasdm": {}, - "@recoveryKeyLost": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@deviceKeys": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@youJoinedTheChat": {}, - "@markAsRead": {}, - "@widgetName": {}, - "@errorAddingWidget": {}, - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "@commandHint_hug": {}, - "@replace": {}, - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "@newSpace": {}, - "@emojis": {}, - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@hydrateTorLong": {}, - "@time": {}, - "@custom": {}, - "@noBackupWarning": {}, - "@storeInSecureStorageDescription": {}, - "@openChat": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@pinMessage": {}, - "@invite": {}, - "@indexedDbErrorTitle": {}, - "@unsupportedAndroidVersionLong": {}, - "@storeSecurlyOnThisDevice": {}, - "@screenSharingDetail": {}, - "@placeCall": {} -} \ No newline at end of file + "you": "Tú", + "@you": { + "type": "text", + "placeholders": {} + }, + "yes": "Tá", + "@yes": { + "type": "text", + "placeholders": {} + }, + "warning": "Rabhadh!", + "@warning": { + "type": "text", + "placeholders": {} + }, + "wallpaper": "Cúlbhrat", + "@wallpaper": { + "type": "text", + "placeholders": {} + }, + "verify": "Deimhnigh", + "@verify": { + "type": "text", + "placeholders": {} + }, + "verified": "Deimhnithe", + "@verified": { + "type": "text", + "placeholders": {} + }, + "username": "Ainm úsáideora", + "@username": { + "type": "text", + "placeholders": {} + }, + "unpin": "Bain biorán", + "@unpin": { + "type": "text", + "placeholders": {} + }, + "unavailable": "Níl ar fáil", + "@unavailable": { + "type": "text", + "placeholders": {} + }, + "title": "FluffyChat", + "@title": { + "description": "Title for the application", + "type": "text", + "placeholders": {} + }, + "systemTheme": "Córas", + "@systemTheme": { + "type": "text", + "placeholders": {} + }, + "submit": "Cuir isteach", + "@submit": { + "type": "text", + "placeholders": {} + }, + "statusExampleMessage": "Conas atá tú inniu?", + "@statusExampleMessage": { + "type": "text", + "placeholders": {} + }, + "status": "Staid", + "@status": { + "type": "text", + "placeholders": {} + }, + "skip": "Léim", + "@skip": { + "type": "text", + "placeholders": {} + }, + "share": "Roinn", + "@share": { + "type": "text", + "placeholders": {} + }, + "settings": "Socruithe", + "@settings": { + "type": "text", + "placeholders": {} + }, + "send": "Seol", + "@send": { + "type": "text", + "placeholders": {} + }, + "security": "Slándáil", + "@security": { + "type": "text", + "placeholders": {} + }, + "search": "Cuardaigh", + "@search": { + "type": "text", + "placeholders": {} + }, + "reply": "Freagair", + "@reply": { + "type": "text", + "placeholders": {} + }, + "remove": "Bain", + "@remove": { + "type": "text", + "placeholders": {} + }, + "rejoin": "Téigh ar ais isteach", + "@rejoin": { + "type": "text", + "placeholders": {} + }, + "reject": "Diúltaigh", + "@reject": { + "type": "text", + "placeholders": {} + }, + "register": "Cláraigh", + "@register": { + "type": "text", + "placeholders": {} + }, + "recording": "Ag Taifeadadh", + "@recording": { + "type": "text", + "placeholders": {} + }, + "reason": "Fáth", + "@reason": { + "type": "text", + "placeholders": {} + }, + "privacy": "Príobháideacht", + "@privacy": { + "type": "text", + "placeholders": {} + }, + "pin": "Biorán", + "@pin": { + "type": "text", + "placeholders": {} + }, + "people": "Daoine", + "@people": { + "type": "text", + "placeholders": {} + }, + "password": "Pasfhocal", + "@password": { + "type": "text", + "placeholders": {} + }, + "participant": "Rannpháirtí", + "@participant": { + "type": "text", + "placeholders": {} + }, + "directChats": "Comhráite Díreacha", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "deviceId": "ID gléis", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "Scrios an teachtaireacht", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "Scrios an cuntas", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "createNewSpace": "Spás nua", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "countParticipants": "{count} rannpháirtithe", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "or": "Nó", + "@or": { + "type": "text", + "placeholders": {} + }, + "online": "Ar líne", + "@online": { + "type": "text", + "placeholders": {} + }, + "ok": "togha", + "@ok": { + "type": "text", + "placeholders": {} + }, + "offline": "As líne", + "@offline": { + "type": "text", + "placeholders": {} + }, + "offensive": "Maslach", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "notifications": "Fógraí", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "none": "Aon cheann", + "@none": { + "type": "text", + "placeholders": {} + }, + "no": "Níl", + "@no": { + "type": "text", + "placeholders": {} + }, + "next": "Ar Aghaidh", + "@next": { + "type": "text", + "placeholders": {} + }, + "moderator": "Modhnóir", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "messages": "Teachtaireachtaí", + "@messages": { + "type": "text", + "placeholders": {} + }, + "mention": "Luaigh", + "@mention": { + "type": "text", + "placeholders": {} + }, + "logout": "Logáil amach", + "@logout": { + "type": "text", + "placeholders": {} + }, + "login": "Logáil isteach", + "@login": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "Solas", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "license": "Ceadúnas", + "@license": { + "type": "text", + "placeholders": {} + }, + "leave": "Fág", + "@leave": { + "type": "text", + "placeholders": {} + }, + "invited": "Le cuireadh", + "@invited": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "Neamhurchóideach", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "ignore": "Tabhair neamhaird ar", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "identity": "Aitheantas", + "@identity": { + "type": "text", + "placeholders": {} + }, + "id": "ID", + "@id": { + "type": "text", + "placeholders": {} + }, + "help": "Cabhair", + "@help": { + "type": "text", + "placeholders": {} + }, + "groups": "Grúpaí", + "@groups": { + "type": "text", + "placeholders": {} + }, + "group": "Grúpa", + "@group": { + "type": "text", + "placeholders": {} + }, + "forward": "Seol ar aghaidh", + "@forward": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "homeserver": "Freastalaí baile", + "@homeserver": {}, + "encryption": "Criptiúchán", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "encrypted": "Criptithe", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "edit": "Cuir in eagar", + "@edit": { + "type": "text", + "placeholders": {} + }, + "devices": "Gléasanna", + "@devices": { + "type": "text", + "placeholders": {} + }, + "device": "Gléas", + "@device": { + "type": "text", + "placeholders": {} + }, + "delete": "Scrios", + "@delete": { + "type": "text", + "placeholders": {} + }, + "dateWithYear": "{day}/{month}/{year}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "dateWithoutYear": "{day}/{month}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "containsUserName": "Coinníonn sé ainm úsáideora", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "configureChat": "Cumraigh comhrá", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "commandInvalid": "Ordú neamhbhailí", + "@commandInvalid": { + "type": "text" + }, + "commandHint_send": "Seol téacs", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "commandHint_me": "Déan cur síos ort féin", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "clearArchive": "Glan an cartlann", + "@clearArchive": {}, + "chatDetails": "Sonraí comhrá", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chatBackup": "Cúltaca comhrá", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "changedTheChatAvatar": "D'athraigh {username} abhatár an chomhrá", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changeDeviceName": "Athraigh ainm an ghléis", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "cantOpenUri": "Ní féidir an URI {uri} a oscailt", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "cancel": "Cealaigh", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "botMessages": "Teachtaireachtaí bota", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "blocked": "Bactha", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "blockDevice": "Bac Gléas", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "Chuir {username} cosc ar {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "banned": "Coiscthe", + "@banned": { + "type": "text", + "placeholders": {} + }, + "banFromChat": "Toirmisc ón gcomhrá", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "sendOnEnter": "Seol ar iontráil", + "@sendOnEnter": {}, + "archive": "Cartlann", + "@archive": { + "type": "text", + "placeholders": {} + }, + "appLock": "Bac aip", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "anyoneCanJoin": "Is féidir le aon duine dul isteach", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "D'fhreagair {senderName} an glao", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "allChats": "Gach comhrá", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "all": "Gach", + "@all": { + "type": "text", + "placeholders": {} + }, + "alias": "ailias", + "@alias": { + "type": "text", + "placeholders": {} + }, + "admin": "Riarthóir", + "@admin": { + "type": "text", + "placeholders": {} + }, + "addToSpace": "Cuir go spás", + "@addToSpace": {}, + "addEmail": "Cuir ríomhphoist", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "Thosaigh {username} an criptiú ó dheireadh go deireadh", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "account": "Cuntas", + "@account": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "Ghlac {username} leis an cuireadh", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "accept": "Glac", + "@accept": { + "type": "text", + "placeholders": {} + }, + "about": "Faoi", + "@about": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "Glac leis an iarratas fíoraithe seo ó {username}?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "areYouSureYouWantToLogout": "An bhfuil tú cinnte gur mhaith leat logáil amach?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "An bhfuil tú cinnte?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "An bhfuil cead ag aoi-úsáideoirí a bheith páirteach", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "invitedUser": "Thug {username} cuireadh do {targetName}", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "hideRedactedEvents": "Folaigh imeachtaí athdhéanta", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "Is féidir le haíonna páirt a ghlacadh", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "guestsAreForbidden": "Tá cosc ar aíonna", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "groupWith": "Grúpa le {displayname}", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "groupIsPublic": "Tá an grúpa poiblí", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "fromTheInvitation": "Ón gcuireadh", + "@fromTheInvitation": { + "type": "text", + "placeholders": {} + }, + "enterYourHomeserver": "Cuir isteach do fhreastalaí baile", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "emoteInvalid": "Gearrchód emote neamhbhailí!", + "@emoteInvalid": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "Tá iomaite ann cheana féin!", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "Cuir in eagar abhatár an tseomra", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "Cuir ailiasanna an tseomra in eagar", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "Cuir freastalaí blocáilte in eagar", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "Leibhéal ceada réamhshocraithe", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "unblockDevice": "Díbhlocáil Gléas", + "@unblockDevice": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "Tugadh cuireadh don theagmháil a thar isteach sa grúpa", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "Déan comparáid idir na huimhreacha seo a leanas agus déan cinnte go bhfuil na huimhreacha seo a leanas ag teacht le huimhreacha an ghléis eile:", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "compareEmojiMatch": "Déan comparáid agus déan cinnte go bhfuil an emoji seo a leanas comhoiriúnach le emoji an ghléis eile:", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "commandMissing": "Ní ordú é {command}.", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "commandHint_react": "Seol freagra mar fhreagairt", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "commandHint_op": "Socraigh leibhéal cumhachta an úsáideora áirithe (réamhshocrú: 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_myroomnick": "Socraigh d'ainm taispeána don seomra seo", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "commandHint_myroomavatar": "Cuir do phictiúr don seomra seo (le mxc-uri)", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_kick": "Bain an t-úsáideoir áirithe den seomra seo", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_join": "Téigh isteach sa seomra áirithe", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_ban": "Cuir cosc ar an úsáideoir áirithe ón seomra seo", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_invite": "Cuir cosc ar an úsáideoir áirithe ón seomra seo", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "chooseAStrongPassword": "Roghnaigh pasfhocal láidir", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "chatHasBeenAddedToThisSpace": "Cuireadh comhrá leis an spás seo", + "@chatHasBeenAddedToThisSpace": {}, + "chatBackupDescription": "Tá do chúltaca comhrá daingnithe le heochair slándála. Déan cinnte nach gcaillfidh tú é.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "channelCorruptedDecryptError": "Truaillíodh an criptiú", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "Athraigh ainm an ghrúpa", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "changedTheRoomInvitationLink": "D'athraigh {username} nasc an chuiridh", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "D'athraigh {username} ailiasanna an tseomra", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheProfileAvatar": "D'athraigh {username} a n-abhatár", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheJoinRulesTo": "D'athraigh {username} na rialacha ceangail go: {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheJoinRules": "D'athraigh {username} na rialacha ceangail", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibilityTo": "D'athraigh {username} infheictheacht na staire go: {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheHistoryVisibility": "D'athraigh {username} infheictheacht na staire", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "D'athraigh {username} a n-ainm taispeána go: '{displayname}'", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheChatPermissions": "D'athraigh {username} na ceadanna comhrá", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatNameTo": "D'athraigh {username} an t-ainm comhrá go: '{chatname}'", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changedTheChatDescriptionTo": "D'athraigh {username} an cur síos comhrá go: '{description}'", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "autoplayImages": "Seinn greamáin agus straoiseog beoite go huathoibríoch", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "createdTheChat": "Rinne {username} an comhrá", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "copyToClipboard": "Cóipeáil ar an ghearrthaisce", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "Cóipeáilte ar an ghearrthaisce", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "Coinníonn sé ainm taispeána", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "commandHint_plain": "Seol téacs neamhfhoirmithe", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_leave": "Fág an seomra seo", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_html": "Seol téacs HTML-formáidithe", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "changeYourAvatar": "Athraigh do abhatár", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "Athraigh do stíl", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheHomeserver": "Athraigh an freastalaí baile", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "voiceMessage": "Glórphost", + "@voiceMessage": { + "type": "text", + "placeholders": {} + }, + "videoCall": "Físghlao", + "@videoCall": { + "type": "text", + "placeholders": {} + }, + "verifyStart": "Tosaigh Fíorú", + "@verifyStart": { + "type": "text", + "placeholders": {} + }, + "unmuteChat": "Neamhciúnaigh comhrá", + "@unmuteChat": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "Folaigh imeachtaí anaithnide", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "unknownDevice": "Gléas anaithnid", + "@unknownDevice": { + "type": "text", + "placeholders": {} + }, + "toggleUnread": "Marcáil Léite/Neamhléite", + "@toggleUnread": { + "type": "text", + "placeholders": {} + }, + "toggleMuted": "Scoránaigh mar ciúnaithe", + "@toggleMuted": { + "type": "text", + "placeholders": {} + }, + "toggleFavorite": "Scoránaigh mar ceann is fearr leat", + "@toggleFavorite": { + "type": "text", + "placeholders": {} + }, + "theyMatch": "Tá siad céanna", + "@theyMatch": { + "type": "text", + "placeholders": {} + }, + "spaceName": "Ainm an spáis", + "@spaceName": { + "type": "text", + "placeholders": {} + }, + "sourceCode": "Cód foinseach", + "@sourceCode": { + "type": "text", + "placeholders": {} + }, + "showPassword": "Taispeáin pasfhocal", + "@showPassword": { + "type": "text", + "placeholders": {} + }, + "shareLocation": "Roinn suíomh", + "@shareLocation": { + "type": "text", + "placeholders": {} + }, + "setStatus": "Cuir stádas", + "@setStatus": { + "type": "text", + "placeholders": {} + }, + "sendVideo": "Seol físeán", + "@sendVideo": { + "type": "text", + "placeholders": {} + }, + "sendSticker": "Seol greamán", + "@sendSticker": { + "type": "text", + "placeholders": {} + }, + "sendOriginal": "Seol an bunchóip", + "@sendOriginal": { + "type": "text", + "placeholders": {} + }, + "sendMessages": "Seol teachtaireachtaí", + "@sendMessages": { + "type": "text", + "placeholders": {} + }, + "sendImage": "Seol íomhá", + "@sendImage": { + "type": "text", + "placeholders": {} + }, + "sendFile": "Seol comhad", + "@sendFile": { + "type": "text", + "placeholders": {} + }, + "sendAudio": "Seol fuaim", + "@sendAudio": { + "type": "text", + "placeholders": {} + }, + "saveFile": "Sábháil comhad", + "@saveFile": { + "type": "text", + "placeholders": {} + }, + "roomVersion": "Leagan seomra", + "@roomVersion": { + "type": "text", + "placeholders": {} + }, + "requestPermission": "Iarr cead", + "@requestPermission": { + "type": "text", + "placeholders": {} + }, + "reportMessage": "Tuairiscigh teachtaireacht", + "@reportMessage": { + "type": "text", + "placeholders": {} + }, + "removeDevice": "Bain gléas", + "@removeDevice": { + "type": "text", + "placeholders": {} + }, + "redactMessage": "Bain teachtaireacht amach", + "@redactMessage": { + "type": "text", + "placeholders": {} + }, + "pushRules": "Rialacha na bhfógraí", + "@pushRules": { + "type": "text", + "placeholders": {} + }, + "publicRooms": "Seomraí Poiblí", + "@publicRooms": { + "type": "text", + "placeholders": {} + }, + "pleaseChoose": "Roghnaigh le do thoil", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "play": "Seinn {fileName}", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "passwordRecovery": "Aisfháil pasfhocail", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "Pasfhocal dearmadta", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "openCamera": "Oscail ceamara", + "@openCamera": { + "type": "text", + "placeholders": {} + }, + "obtainingLocation": "ag Aimsiú an suíomh…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "noPermission": "Gan cead", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "newChat": "Comhrá nua", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "muteChat": "Ciúnaigh comhrá", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "memberChanges": "Athruithe ball", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "loadMore": "Lódáil níos mó…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "joinRoom": "Téigh isteach sa seomra", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "isTyping": "ag clóscríobh…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "Tabhair cuireadh do theagmháil", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "Úsáideoirí a dtugann tú neamhaird orthu", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "fromJoining": "Ó tar isteach", + "@fromJoining": { + "type": "text", + "placeholders": {} + }, + "fontSize": "Méid cló", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "Tosaigh criptiú", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "Cuir ainm taispeána in eagar", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "currentlyActive": "Gníomhach faoi láthair", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "fileName": "Ainm an chomhaid", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "everythingReady": "Gach rud réidh!", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "emptyChat": "Comhrá folamh", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "emoteShortcode": "Gearrchód straoiseoige", + "@emoteShortcode": { + "type": "text", + "placeholders": {} + }, + "emoteSettings": "Socruithe straoiseoige", + "@emoteSettings": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "Íoslódáil comhad", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "changePassword": "Athraigh an pasfhocal", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "Dorcha", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "create": "Cruthaigh", + "@create": { + "type": "text", + "placeholders": {} + }, + "copy": "Cóipeáil", + "@copy": { + "type": "text", + "placeholders": {} + }, + "connect": "Ceangail", + "@connect": { + "type": "text", + "placeholders": {} + }, + "confirm": "Deimhnigh", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "close": "Dún", + "@close": { + "type": "text", + "placeholders": {} + }, + "chats": "Comhráite", + "@chats": { + "type": "text", + "placeholders": {} + }, + "chat": "Comhrá", + "@chat": { + "type": "text", + "placeholders": {} + }, + "scanQrCode": "Scan cód QR", + "@scanQrCode": {}, + "inviteText": "Thug {username} cuireadh duit chuig FluffyChat.\n1. Suiteáil FluffyChat: https://fluffychat.im\n2. Cláraigh nó sínigh isteach\n3. Oscail an nasc cuiridh: {link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "noMatrixServer": "Níl {server1} freastalaí Matrix. Úsáid {server2} ina áit sin?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "noGoogleServicesWarning": "Dealraíonn sé nach bhfuil aon seirbhísí google agat ar do ghuthán. Sin cinneadh maith le do phríobháideacht! Chun fógraí brú a fháil i FluffyChat molaimid https://microg.org/ nó https://unifiedpush.org/ a úsáid.", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "Ní féidir leat criptiú a ghníomhachtú ach a luaithe nach bhfuil an seomra inrochtana go poiblí a thuilleadh.", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "noEmotesFound": "Níor aimsíodh aon straoiseoga. 😕", + "@noEmotesFound": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "Gan aon nasc leis an bhfreastalaí", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "newVerificationRequest": "Iarratas fíoraithe nua!", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "Teachtaireacht nua i FluffyChat", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "Bí ar an eolas go dteastaíonn Pantalaimon uait chun criptiú ó cheann go ceann a úsáid anois.", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "logInTo": "Logáil isteach chuig {homeserver}", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "locationPermissionDeniedNotice": "Diúltaíodh cead suímh. Deonaigh dóibh le do thoil go mbeidh tú in ann do shuíomh a roinnt.", + "@locationPermissionDeniedNotice": { + "type": "text", + "placeholders": {} + }, + "locationDisabledNotice": "Tá seirbhísí suímh díchumasaithe. Cuir ar a gcumas le do thoil a bheith in ann do shuíomh a roinnt.", + "@locationDisabledNotice": { + "type": "text", + "placeholders": {} + }, + "loadingPleaseWait": "Ag lódáil… Fan, le do thoil.", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "loadCountMoreParticipants": "Lódáil {count} níos mó rannpháirtithe", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "leftTheChat": "Fágadh an comhrá", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "lastActiveAgo": "Gníomhach deireanach: {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "kickFromChat": "Caith é amach as an comhrá", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "kicked": "Chaith {username} {targetName} amach", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickedAndBanned": "Chaith {username} amach agus chuir cosc ar {targetName} freisin", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "joinedTheChat": "Tháinig {username} isteach sa chomhrá", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "invitedUsersOnly": "Úsáideoirí le cuireadh amháin", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "Tabhair cuireadh do theagmháil chuig {groupName}", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "incorrectPassphraseOrKey": "Pasfhrása nó eochair téarnaimh mícheart", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "Chliceáil mé ar an nasc", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "howOffensiveIsThisContent": "Cé chomh maslach atá an t-ábhar seo?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "extremeOffensive": "Fíor-maslach", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "hasWithdrawnTheInvitationFor": "Tharraing {username} an cuireadh do {targetName} siar", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "goToTheNewRoom": "Téigh go dtí an seomra nua", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "errorObtainingLocation": "Earráid maidir le suíomh a fháil: {error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "enterAnEmailAddress": "Cuir isteach seoladh ríomhphoist", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "Chuir {senderName} deireadh leis an nglao", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "encryptionNotEnabled": "Ní chumasaítear criptiú", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "enableEncryptionWarning": "Ní bheidh in ann an criptiú a dhíchumasú níos mó. An bhfuil tú cinnte?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "enableEmotesGlobally": "Cumasaigh pacáiste straoiseoige go huilíoch", + "@enableEmotesGlobally": { + "type": "text", + "placeholders": {} + }, + "emoteWarnNeedToPick": "Caithfidh tú gearrchód straoiseoige agus íomhá a roghnú!", + "@emoteWarnNeedToPick": { + "type": "text", + "placeholders": {} + }, + "emotePacks": "Pacáistí straoiseoige don seomra", + "@emotePacks": { + "type": "text", + "placeholders": {} + }, + "displaynameHasBeenChanged": "Athraíodh an t-ainm taispeána", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "deactivateAccountWarning": "Díghníomhachtaeoidh sé seo do chuntas úsáideora. Ní féidir é seo a chealú! An bhfuil tú cinnte?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "Níorbh fhéidir teachtaireacht a dhíchriptiú: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "contentHasBeenReported": "Tuairiscíodh an t-ábhar do lucht riaracháin an fhreastalaí", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "commandHint_unban": "Cuir deireadh an cosc den úsáideoir áirithe ón seomra seo", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "changedTheGuestAccessRulesTo": "D'athraigh {username} na rialacha maidir le rochtain aoi chuig: {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheGuestAccessRules": "D'athraigh {username} na rialacha rochtana aoi", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "badServerVersionsException": "Tá na leaganacha sonraíochta seo ar fáil faoin freastalaí baile:\n{serverVersions}\nAch níl ach na ceann seo ar fáil faoin aip seo {supportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "badServerLoginTypesException": "Tá na cineálacha logála isteach seo ar fáil faoin freastalaí baile:\n{serverVersions}\nAch níl ach na ceann seo ar fáil faoin aip seo:\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "askSSSSSign": "Chun a bheith in ann an duine eile a shíniú, cuir isteach do phasfhrása stóir sábháilte nó d'eochair téarnaimh.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "yourPublicKey": "D'eochair phoiblí", + "@yourPublicKey": { + "type": "text", + "placeholders": {} + }, + "youHaveBeenBannedFromThisChat": "Cuireadh cosc ort ón gcomhrá seo", + "@youHaveBeenBannedFromThisChat": { + "type": "text", + "placeholders": {} + }, + "youAreNoLongerParticipatingInThisChat": "Níl tú ag glacadh páirte sa chomhrá seo a thuilleadh", + "@youAreNoLongerParticipatingInThisChat": { + "type": "text", + "placeholders": {} + }, + "writeAMessage": "Scríobh teachtaireacht…", + "@writeAMessage": { + "type": "text", + "placeholders": {} + }, + "withTheseAddressesRecoveryDescription": "Leis na seoltaí seo is féidir leat do phasfhocal a athshlánú.", + "@withTheseAddressesRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "wipeChatBackup": "Glan do cúltaca comhrá a chruthú eochair slándála nua?", + "@wipeChatBackup": { + "type": "text", + "placeholders": {} + }, + "whyDoYouWantToReportThis": "Cén fáth ar mhaith leat é seo a thuairisciú?", + "@whyDoYouWantToReportThis": { + "type": "text", + "placeholders": {} + }, + "whoIsAllowedToJoinThisGroup": "Cé a bhfuil cead aige/aici dul isteach sa ghrúpa seo", + "@whoIsAllowedToJoinThisGroup": { + "type": "text", + "placeholders": {} + }, + "whoCanPerformWhichAction": "Cé atá in ann an gníomh a dhéanamh", + "@whoCanPerformWhichAction": { + "type": "text", + "placeholders": {} + }, + "verifySuccess": "D'fhíoraigh tú go rathúil!", + "@verifySuccess": { + "type": "text", + "placeholders": {} + }, + "userLeftTheChat": "D'fhág {username} an comhrá", + "@userLeftTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "userAndUserAreTyping": "Tá {username} agus {username2} ag clóscríobh…", + "@userAndUserAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "username2": {} + } + }, + "userAndOthersAreTyping": "tá {username} agus {count} daoine eile ag clóscríobh…", + "@userAndOthersAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "count": {} + } + }, + "unreadChats": "{unreadCount, plural, =1{1 comhrá neamhléite} other{{unreadCount} comhráite neamhléite}}", + "@unreadChats": { + "type": "text", + "placeholders": { + "unreadCount": {} + } + }, + "unknownEncryptionAlgorithm": "Algartam criptithe anaithnid", + "@unknownEncryptionAlgorithm": { + "type": "text", + "placeholders": {} + }, + "unbannedUser": "Chuir {username} deireadh an cosc {targetName}", + "@unbannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "tryToSendAgain": "Déan iarracht a sheoladh arís", + "@tryToSendAgain": { + "type": "text", + "placeholders": {} + }, + "transferFromAnotherDevice": "Aistriú ó ghléas eile", + "@transferFromAnotherDevice": { + "type": "text", + "placeholders": {} + }, + "tooManyRequestsWarning": "An iomarca iarratas. Bain triail eile as níos déanaí!", + "@tooManyRequestsWarning": { + "type": "text", + "placeholders": {} + }, + "theyDontMatch": "Níl siad céanna", + "@theyDontMatch": { + "type": "text", + "placeholders": {} + }, + "sharedTheLocation": "Roinn {username} an suíomh", + "@sharedTheLocation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "setPermissionsLevel": "Socraigh leibhéal ceadanna", + "@setPermissionsLevel": { + "type": "text", + "placeholders": {} + }, + "setInvitationLink": "Socraigh nasc cuiridh", + "@setInvitationLink": { + "type": "text", + "placeholders": {} + }, + "setCustomEmotes": "Socraigh straoiseoga saincheaptha", + "@setCustomEmotes": { + "type": "text", + "placeholders": {} + }, + "setAsCanonicalAlias": "Socraigh mar phríomh-ailias", + "@setAsCanonicalAlias": { + "type": "text", + "placeholders": {} + }, + "sentCallInformations": "Sheol {senderName} faisnéis maidir le glaonna", + "@sentCallInformations": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "sentAVideo": "Sheol {username} físeán", + "@sentAVideo": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentASticker": "Sheol {username} greamán", + "@sentASticker": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAPicture": "Sheol {username} pictiúr", + "@sentAPicture": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "replaceRoomWithNewerVersion": "Cuir leagan seomra níos nuaí in ionad an tseomra", + "@replaceRoomWithNewerVersion": { + "type": "text", + "placeholders": {} + }, + "renderRichContent": "Taispeáin ábhar teachtaireachta saibhir", + "@renderRichContent": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "Bain d'abhatár", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "unbanFromChat": "Cuir deireadh an cosc ón gcomhrá", + "@unbanFromChat": { + "type": "text", + "placeholders": {} + }, + "removedBy": "Bainte de ag {username}", + "@removedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removeAllOtherDevices": "Bain gach gléas eile", + "@removeAllOtherDevices": { + "type": "text", + "placeholders": {} + }, + "rejectedTheInvitation": "Dhiúltaigh {username} don chuireadh", + "@rejectedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "redactedAnEvent": "Rinne {username} cinsire imeacht", + "@redactedAnEvent": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "pleaseFollowInstructionsOnWeb": "Lean na treoracha ar an suíomh gréasáin agus tapáil \"ar aghaidh\".", + "@pleaseFollowInstructionsOnWeb": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "Cuir isteach d'ainm úsáideora le do thoil", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "Cuir isteach d'uimhir PIN le do thoil", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "Iontráil do phasfhocal le do thoil", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "Iontráil 4 dhigit le do thoil nó fág folamh chun glas aipe a dhíchumasú.", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "pleaseClickOnLink": "Cliceáil ar an nasc sa ríomhphost agus ansin lean ar aghaidh.", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "pleaseChooseAPasscode": "Roghnaigh paschód le do thoil", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pickImage": "Roghnaigh íomhá", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "Athraíodh an pasfhocal", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "passphraseOrKey": "pasfhrása nó eochair téarnaimh", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "serverRequiresEmail": "Ní mór don fhreastalaí seo do sheoladh ríomhphoist a bhailíochtú le haghaidh clárúcháin.", + "@serverRequiresEmail": {}, + "openInMaps": "Oscail i léarscáileanna", + "@openInMaps": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "Oscail an aip chun teachtaireachtaí a léamh", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "Úps, chuaigh rud éigin mícheart …", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "Hoips! Ar an drochuair, tharla earráid nuair a bhí na fógraí brú á mbunú.", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "onlineKeyBackupEnabled": "Tá Cúltaca Eochair Ar Líne cumasaithe", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "numUsersTyping": "Tá {count} úsáideoirí ag clóscríobh…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "notificationsEnabledForThisAccount": "Fógraí cumasaithe don chuntas seo", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "Níor aimsíodh aon seomraí…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "Níor chuir tú bealach leis do phasfhocal a aisghabháil fós.", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "inviteForMe": "Tabhair cuireadh dom", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "weSentYouAnEmail": "Sheolamar ríomhphost chugat", + "@weSentYouAnEmail": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerNumbers": "Ag fanacht le comhpháirtí glacadh leis na huimhreacha …", + "@waitingPartnerNumbers": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerEmoji": "Ag fanacht le comhpháirtí glacadh leis na straoiseoga…", + "@waitingPartnerEmoji": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerAcceptRequest": "Ag fanacht le comhpháirtí glacadh leis an iarratas…", + "@waitingPartnerAcceptRequest": { + "type": "text", + "placeholders": {} + }, + "visibleForEveryone": "Infheicthe do gach duine", + "@visibleForEveryone": { + "type": "text", + "placeholders": {} + }, + "visibleForAllParticipants": "Infheicthe do na rannpháirtithe go léir", + "@visibleForAllParticipants": { + "type": "text", + "placeholders": {} + }, + "visibilityOfTheChatHistory": "Infheictheacht stair na comhrá", + "@visibilityOfTheChatHistory": { + "type": "text", + "placeholders": {} + }, + "verifyTitle": "Ag fíorú cuntas eile", + "@verifyTitle": { + "type": "text", + "placeholders": {} + }, + "userSentUnknownEvent": "Sheol {username} imeacht {type}", + "@userSentUnknownEvent": { + "type": "text", + "placeholders": { + "username": {}, + "type": {} + } + }, + "userIsTyping": "Tá {username} ag clóscríobh…", + "@userIsTyping": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "unknownEvent": "Imeacht anaithnid '{type}'", + "@unknownEvent": { + "type": "text", + "placeholders": { + "type": {} + } + }, + "synchronizingPleaseWait": "Ag sioncrónú... Fan, le do thoil.", + "@synchronizingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "startedACall": "Thosaigh {senderName} glao", + "@startedACall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "spaceIsPublic": "Tá an spás poiblí", + "@spaceIsPublic": { + "type": "text", + "placeholders": {} + }, + "singlesignon": "Sínigh Aonair ar", + "@singlesignon": { + "type": "text", + "placeholders": {} + }, + "sentAnAudio": "Sheol {username} fuaim", + "@sentAnAudio": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAFile": "Sheol {username} comhad", + "@sentAFile": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sendAsText": "Seol mar théacs", + "@sendAsText": { + "type": "text" + }, + "sendAMessage": "Seol teachtaireacht", + "@sendAMessage": { + "type": "text", + "placeholders": {} + }, + "seenByUser": "Le feiceáil ag {username}", + "@seenByUser": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "roomHasBeenUpgraded": "Uasghrádaíodh an seomra", + "@roomHasBeenUpgraded": { + "type": "text", + "placeholders": {} + }, + "addAccount": "Breisigh cuntas", + "@addAccount": {}, + "enableMultiAccounts": "(BÉITE) Cumasaigh cuntais iomadúla ar an gléas seo", + "@enableMultiAccounts": {}, + "commandHint_create": "Cruthaigh comhrá grúpa folamh\nÚsáid --no-encryption chun criptiúchán a dhíchumasú", + "@commandHint_create": { + "type": "text", + "description": "Usage hint for the command /create" + }, + "link": "Nasc", + "@link": {}, + "commandHint_clearcache": "Glan an taisce", + "@commandHint_clearcache": { + "type": "text", + "description": "Usage hint for the command /clearcache" + }, + "videoCallsBetaWarning": "Tabhair faoi deara go bhfuil físglaonna i béite. B'fhéidir nach bhfeidhmíonn siad ar gach ardán chomh atá súil aige ná ar bith.", + "@videoCallsBetaWarning": {}, + "emailOrUsername": "Ríomhphost nó ainm úsáideora", + "@emailOrUsername": {}, + "repeatPassword": "Scríobh an pasfhocal arís", + "@repeatPassword": {}, + "yourChatBackupHasBeenSetUp": "Bunaíodh do chúltaca comhrá.", + "@yourChatBackupHasBeenSetUp": {}, + "openVideoCamera": "Oscail físcheamara", + "@openVideoCamera": { + "type": "text", + "placeholders": {} + } +} diff --git a/assets/l10n/intl_gl.arb b/assets/l10n/intl_gl.arb index 919b035c2..55c4f8790 100644 --- a/assets/l10n/intl_gl.arb +++ b/assets/l10n/intl_gl.arb @@ -190,7 +190,7 @@ "description": {} } }, - "changedTheChatNameTo": "{username} mudou o nome da conversa a: '{chatname}'", + "changedTheChatNameTo": "{username} mudou o nome da charla a: '{chatname}'", "@changedTheChatNameTo": { "type": "text", "placeholders": { @@ -559,7 +559,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "Nivel de permisos por omisión", + "defaultPermissionLevel": "Nivel de permisos por defecto para novas usuarias", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -1931,7 +1931,7 @@ "@oneClientLoggedOut": {}, "link": "Ligazón", "@link": {}, - "yourChatBackupHasBeenSetUp": "Configurouse a copia de apoio do chat.", + "yourChatBackupHasBeenSetUp": "Configurouse a copia de apoio da charla.", "@yourChatBackupHasBeenSetUp": {}, "unverified": "Sen verificar", "@unverified": {}, @@ -1968,7 +1968,7 @@ "type": "text", "description": "Usage hint for the command /clearcache" }, - "commandHint_dm": "Iniciar un chat directo\nUsa --no-encryption para desactivar a cifraxe", + "commandHint_dm": "Iniciar unha charla directa\nUsa --no-encryption para desactivar a cifraxe", "@commandHint_dm": { "type": "text", "description": "Usage hint for the command /dm" @@ -2141,7 +2141,7 @@ }, "unlockOldMessages": "Desbloquear mensaxes antigas", "@unlockOldMessages": {}, - "dehydrateTorLong": "Para usuarias de TOR, é recomendable exportar a sesión antes de pechar a ventál.", + "dehydrateTorLong": "Para usuarias de TOR, é recomendable exportar a sesión antes de pechar a xanela.", "@dehydrateTorLong": {}, "hydrateTor": "Usuarias TOR: Importar a sesión exportada", "@hydrateTor": {}, @@ -2198,7 +2198,7 @@ "@callingAccount": {}, "callingAccountDetails": "Permítelle a FluffyChat usar a app marcador nativa de android.", "@callingAccountDetails": {}, - "appearOnTopDetails": "Permítelle á app aparecer por enrriba (non é preciso se xa configuraches FluffyChat como unha conta para chamadas)", + "appearOnTopDetails": "Permítelle á app aparecer por enriba (non é preciso se xa configuraches FluffyChat como unha conta para chamadas)", "@appearOnTopDetails": {}, "enterSpace": "Entrar no espazo", "@enterSpace": {}, @@ -2206,7 +2206,7 @@ "@enterRoom": {}, "allSpaces": "Todos os espazos", "@allSpaces": {}, - "screenSharingDetail": "Estás compartindo a túa pantalla en FluffyChat", + "screenSharingDetail": "Estás a compartir a túa pantalla en FluffyChat", "@screenSharingDetail": {}, "numChats": "{number} conversas", "@numChats": { @@ -2394,7 +2394,7 @@ "@pushNotificationsNotAvailable": {}, "makeAdminDescription": "Cando convirtas a esta usuaria en admin non poderás desfacer a acción xa que terá os mesmos permisos ca ti.", "@makeAdminDescription": {}, - "archiveRoomDescription": "Vaise mover o chat ao arquivo. Outras usuarias poderán ver que saíches da conversa.", + "archiveRoomDescription": "Vaise mover a charla ao arquivo. Outras usuarias poderán ver que saíches da conversa.", "@archiveRoomDescription": {}, "invalidInput": "Contido non válido!", "@invalidInput": {}, @@ -2413,7 +2413,7 @@ }, "learnMore": "Saber máis", "@learnMore": {}, - "roomUpgradeDescription": "Vaise recrear o chat coa nova versión da sala. Todas as participantes recibirán unha notificación para que cambien ao novo chat. Podes ler máis información acerca das versións das salas en https://spec.matrix.org/latest/rooms/", + "roomUpgradeDescription": "Vaise recrear a charla coa nova versión da sala. Todas as participantes recibirán unha notificación para que cambien á nova charla. Podes ler máis información acerca das versións das salas en https://spec.matrix.org/latest/rooms/", "@roomUpgradeDescription": {}, "pleaseEnterANumber": "Escribe un número maior de cero", "@pleaseEnterANumber": {}, @@ -2474,7 +2474,7 @@ "@select": {}, "pleaseChooseAStrongPassword": "Elixe un contrasinal forte", "@pleaseChooseAStrongPassword": {}, - "addChatOrSubSpace": "Engadir chat ou sub espazo", + "addChatOrSubSpace": "Engadir charla ou sub espazo", "@addChatOrSubSpace": {}, "leaveEmptyToClearStatus": "Deixa baleiro para limpar o teu estado.", "@leaveEmptyToClearStatus": {}, @@ -2530,7 +2530,7 @@ "@verifyOtherDevice": {}, "verifyOtherUser": "🔐 Verificar outra usuaria", "@verifyOtherUser": {}, - "verifyOtherDeviceDescription": "Ao verificar outro dispositivo estás compartindo as chaves, aumentando a túa seguridade 💪. Ao iniciar a verificación aparecerá unha ventá emerxente nos dous dispositivos. Nesa ventá verás varios emojis ou números que tes que comparar entre eles. O mellor xeito de facelo é ter os dous dispositivos contigo cando inicias o proceso de verificación. 🤳", + "verifyOtherDeviceDescription": "Ao verificar outro dispositivo estás compartindo as chaves, aumentando a túa seguridade 💪. Ao iniciar a verificación aparecerá unha xanela emerxente nos dous dispositivos. Nesa xanela verás varios emojis ou números que tes que comparar entre eles. O mellor xeito de facelo é ter os dous dispositivos contigo cando inicias o proceso de verificación. 🤳", "@verifyOtherDeviceDescription": {}, "canceledKeyVerification": "{sender} desbotou a verificación da chave", "@canceledKeyVerification": { @@ -2557,7 +2557,7 @@ "@sendTypingNotificationsDescription": {}, "formattedMessagesDescription": "Mostrar texto enriquecido nas mensaxes como letra grosa usando markdown.", "@formattedMessagesDescription": {}, - "verifyOtherUserDescription": "Se verificas a outra usuaria, podes ter a certeza de que sabes con quen estás a conversar. 💪\n\nAo iniciar a verificación, ti mais a outra usuaria veredes unha ventá emerxente na app onde aparecerán varios emojis ou números que teredes que comparar entre vós.\n\nO mellor xeito de facelo é en persoa o cunha chamada de vídeo. 👭", + "verifyOtherUserDescription": "Se verificas a outra usuaria, podes ter a certeza de que sabes con quen estás a conversar. 💪\n\nAo iniciar a verificación, ti mais a outra usuaria veredes unha xanela emerxente na app onde aparecerán varios emojis ou números que teredes que comparar entre vós.\n\nO mellor xeito de facelo é en persoa o cunha chamada de vídeo. 👭", "@verifyOtherUserDescription": {}, "requestedKeyVerification": "{sender} solicitou verificar a chave", "@requestedKeyVerification": { @@ -2609,7 +2609,7 @@ "@commandHint_ignore": {}, "commandHint_unignore": "Non ignorar o ID matrix indicado", "@commandHint_unignore": {}, - "unreadChatsInApp": "{appname}: {unread} chats sen ler", + "unreadChatsInApp": "{appname}: {unread} charlas sen ler", "@unreadChatsInApp": { "type": "text", "placeholders": { @@ -2621,7 +2621,7 @@ "@noDatabaseEncryption": {}, "accessAndVisibility": "Acceso e Visibilidade", "@accessAndVisibility": {}, - "accessAndVisibilityDescription": "Quen pode unirse a este chat de que xeito pode ser atopado.", + "accessAndVisibilityDescription": "Quen pode unirse a esta charla e de que xeito e como poden atopala.", "@accessAndVisibilityDescription": {}, "customEmojisAndStickers": "Emojis personais e adhesivos", "@customEmojisAndStickers": {}, @@ -2629,19 +2629,19 @@ "@calls": {}, "hideRedactedMessages": "Agochar mensaxes editadas", "@hideRedactedMessages": {}, - "hideRedactedMessagesBody": "Se alguén corrixe unha mensaxe entón esta xa non será visible no chat.", + "hideRedactedMessagesBody": "Se alguén corrixe unha mensaxe entón esta xa non será visible na charla.", "@hideRedactedMessagesBody": {}, "hideInvalidOrUnknownMessageFormats": "Agochar formatos de mensaxe non válidos ou descoñecidos", "@hideInvalidOrUnknownMessageFormats": {}, - "hideMemberChangesInPublicChats": "Agochar cambios dos membros nos chats públicos", + "hideMemberChangesInPublicChats": "Agochar cambios dos membros nas charlas públicas", "@hideMemberChangesInPublicChats": {}, "notifyMeFor": "Notificarme sobre", "@notifyMeFor": {}, - "hideMemberChangesInPublicChatsBody": "Non mostrar na cronoloxía se alguén se une ou deixa un chat público, para mellorar a lexibilidade.", + "hideMemberChangesInPublicChatsBody": "Non mostrar na cronoloxía se alguén se une ou deixa unha conversa pública, para mellorar a lexibilidade.", "@hideMemberChangesInPublicChatsBody": {}, "usersMustKnock": "As usuarias teñen que pedir entrar", "@usersMustKnock": {}, - "userWouldLikeToChangeTheChat": "{user} quere unirse ao chat.", + "userWouldLikeToChangeTheChat": "{user} quere unirse á charla.", "@userWouldLikeToChangeTheChat": { "placeholders": { "user": {} @@ -2649,7 +2649,7 @@ }, "knocking": "A solicitar", "@knocking": {}, - "chatCanBeDiscoveredViaSearchOnServer": "O chat pode ser atopado ao buscar en {server}", + "chatCanBeDiscoveredViaSearchOnServer": "A charla pode ser atopada ao buscar en {server}", "@chatCanBeDiscoveredViaSearchOnServer": { "type": "text", "placeholders": { @@ -2660,9 +2660,9 @@ "@createNewAddress": {}, "appLockDescription": "Bloquear a app cun código PIN cando non a uses", "@appLockDescription": {}, - "globalChatId": "ID Global do chat", + "globalChatId": "ID Global da charla", "@globalChatId": {}, - "customEmojisAndStickersBody": "Engade ou comparte emojis personais e adhesivos que poden usarse nos chats.", + "customEmojisAndStickersBody": "Engade ou comparte emojis personais e adhesivos que poden usarse nas charlas.", "@customEmojisAndStickersBody": {}, "overview": "Vista xeral", "@overview": {}, @@ -2679,7 +2679,7 @@ "type": "text", "count": {} }, - "publicChatAddresses": "Enderezos públicos do chat", + "publicChatAddresses": "Enderezos públicos da charla", "@publicChatAddresses": {}, "userRole": "Rol da usuaria", "@userRole": {}, @@ -2690,7 +2690,7 @@ "level": {} } }, - "searchIn": "Buscar no chat \"{chat}\"...", + "searchIn": "Buscar na charla \"{chat}\"...", "@searchIn": { "type": "text", "placeholders": { @@ -2706,5 +2706,102 @@ "knockRestricted": "Peta á porta", "@knockRestricted": {}, "restricted": "Non accesible", - "@restricted": {} + "@restricted": {}, + "swipeRightToLeftToReply": "Despraza hacia a esquerda para responder", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "falso", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "noMoreChatsFound": "Non se atopan máis charlas…", + "@noMoreChatsFound": {}, + "joinedChats": "Charlas nas que participas", + "@joinedChats": {}, + "countChatsAndCountParticipants": "{chats} charlas e {participants} participantes", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "unread": "Sen ler", + "@unread": {}, + "space": "Espazo", + "@space": {}, + "spaces": "Espazos", + "@spaces": {}, + "goToSpace": "Ir ao espazo: {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "Marcar como non lido", + "@markAsUnread": {}, + "userLevel": "{level} - Usuaria", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - Moderadora", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - Administradora", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeGeneralChatSettings": "Cambiar os axustes xerais da charla", + "@changeGeneralChatSettings": {}, + "inviteOtherUsers": "Convidar a outras usuarias a esta charla", + "@inviteOtherUsers": {}, + "changeTheChatPermissions": "Cambiar os permisos na charla", + "@changeTheChatPermissions": {}, + "changeTheVisibilityOfChatHistory": "Cambiar a visibilidade do historial da charla", + "@changeTheVisibilityOfChatHistory": {}, + "changeTheCanonicalRoomAlias": "Cambiar o enderezo público principal da charla", + "@changeTheCanonicalRoomAlias": {}, + "sendRoomNotifications": "Enviar notificacións a @room", + "@sendRoomNotifications": {}, + "changeTheDescriptionOfTheGroup": "Cambiar a descrición da charla", + "@changeTheDescriptionOfTheGroup": {}, + "invitedBy": "📩 Convidada por {user}", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "changelog": "Novidades na versión", + "@changelog": {}, + "chatPermissionsDescription": "Define que nivel de permisos son necesarios para realizar certas accións nesta charla. Os niveis de permiso 0, 50 e 100 normalmente representan, usuarias, moderadoras e administradoras, pero son posibles outras escalas.", + "@chatPermissionsDescription": {}, + "updateInstalled": "🎉 Instalouse a actualización a {version}!", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "sendCanceled": "Cancelouse o envío", + "@sendCanceled": {}, + "noChatsFoundHere": "Sen charlas por aquí. Comeza unha nova conversa con alguén premendo no botón de abaixo. ⤵️", + "@noChatsFoundHere": {}, + "discoverHomeservers": "Atopar servidores", + "@discoverHomeservers": {}, + "whatIsAHomeserver": "Que é un servidor de inicio?", + "@whatIsAHomeserver": {}, + "loginWithMatrixId": "Acceder co ID-Matrix", + "@loginWithMatrixId": {}, + "homeserverDescription": "Todos os teus datos quedan gardados no servidor de inicio, igual que co teu provedor de correo electrónico. Podes elexir o servidor que queres usar e poderás comunicarte con todos os demais. Aprende máis en https://matrix.org.", + "@homeserverDescription": {}, + "doesNotSeemToBeAValidHomeserver": "Non semella ser un servidor de inicio compatible. É o URL correcto?", + "@doesNotSeemToBeAValidHomeserver": {} } diff --git a/assets/l10n/intl_he.arb b/assets/l10n/intl_he.arb index 87d50b339..d33fc8af4 100644 --- a/assets/l10n/intl_he.arb +++ b/assets/l10n/intl_he.arb @@ -1,2129 +1,1301 @@ { - "@@last_modified": "2021-08-14 12:41:10.036931", - "about": "אודות", - "@about": { - "type": "text", - "placeholders": {} - }, - "accept": "קבל", - "@accept": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "{username} קיבל את ההזמנה", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "חשבון", - "@account": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "{username} הפעיל הצפנה מקצה לקצה", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "admin": "מנהל", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "כינוי", - "@alias": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "{senderName} ענה לשיחה", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "כל אחד יכול להצטרף", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "archive": "ארכיון", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "האם משתמשים אורחים מורשים להצטרף", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "האם אתה בטוח?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "כדי שתוכל לחתום על משתמש אחר , הזן את הסיסמה שלך או את מפתח השחזור.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "לקבל בקשת אימות זו מ- {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changePassword": "שנה סיסמא", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "appLock": "נעילת אפליקציה", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "cancel": "ביטול", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "addEmail": "הוסף מייל", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "all": "הכל", - "@all": { - "type": "text", - "placeholders": {} - }, - "allChats": "כל הצ'אטים", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "banned": "חסום", - "@banned": { - "type": "text", - "placeholders": {} - }, - "sendOnEnter": "שלח בכניסה", - "@sendOnEnter": {}, - "badServerLoginTypesException": "שרת הבית תומך בסוגי הכניסה:\n{serverVersions}\nאבל אפליקציה זו תומכת רק ב:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} שינה את כללי הגישה לאורחים ל: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username} שינה את כללי ההצטרפות", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatNameTo": "{username} שינה את שם הצ'אט ל: '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheRoomInvitationLink": "{username} שינה את קישור ההזמנה", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "repeatPassword": "כתוב שוב את הסיסמה", - "@repeatPassword": {}, - "areYouSureYouWantToLogout": "האם אתה בטוח שברצונך לצאת?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "chat": "צ׳אט", - "@chat": { - "type": "text", - "placeholders": {} - }, - "autoplayImages": "הפעל אוטומטית מדבקות ואנימציות מונפשים", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "badServerVersionsException": "שרת הבית תומך בגרסאות:\n{serverVersions}\nאבל האפליקציה הזו תומכת רק ב-{supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "banFromChat": "צאט חסום", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "{username} חסם את {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "blockDevice": "חסום מכשיר", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "חסום", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "botMessages": "הודעות בוט", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "cantOpenUri": "לא ניתן לפתוח את ה-URI {uri}", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "changeDeviceName": "שנה את שם המכשיר", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "{username} שינה את האווטאר של הצ'אט", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatDescriptionTo": "{username} שינה את תיאור הצ'אט ל: '{description}'", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheChatPermissions": "{username} שינה את הרשאות הצ'אט", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "{username} שינה את שם התצוגה שלו ל: '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRules": "{username} שינה את כללי הגישה לאורחים", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibility": "{username} שינה את נראות ההיסטוריה", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "{username} שינה את נראות ההיסטוריה ל: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRulesTo": "{username} שינה את כללי ההצטרפות ל: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheProfileAvatar": "{username} שינה את האווטאר שלו", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "{username} שינה את כינוי החדר", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changeTheHomeserver": "שנה את שרת הבית", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "שנה את הסגנון שלך", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "שנה את שם הקבוצה", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "שינוי האווטאר שלך", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "ההצפנה נפגמה", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "yourChatBackupHasBeenSetUp": "גיבוי הצ'אט שלך הוגדר.", - "@yourChatBackupHasBeenSetUp": {}, - "chatBackup": "גיבוי צ'אט", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "commandHint_ban": "חסום את המשתמש הנתון מהחדר הזה", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_clearcache": "נקה מטמון", - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "commandHint_create": "צור צ'אט קבוצתי ריק\nהשתמש ב--no-encryption כדי להשבית את ההצפנה", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "commandHint_discardsession": "התעלם מהסשן", - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "commandHint_dm": "התחל צ'אט ישיר\nהשתמש ב--no-encryption כדי להשבית את ההצפנה", - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "commandHint_html": "שלח טקסט בתבנית HTML", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "הזמן את המשתמש הנתון לחדר זה", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_join": "הצטרף לחדר הנתון", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_kick": "הסר את המשתמש הנתון מהחדר הזה", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_leave": "עזוב את החדר הזה", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_me": "תאר את עצמך", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "chatDetails": "פרטי צ'אט", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "גיבוי הצ'אט שלך מאובטח באמצעות מפתח אבטחה. אנא וודא שאתה לא מאבד אותו.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "צ'אט נוסף למרחב הזה", - "@chatHasBeenAddedToThisSpace": {}, - "chats": "צ'אטים", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "בחר סיסמה חזקה", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "נקה ארכיון", - "@clearArchive": {}, - "close": "סגור", - "@close": { - "type": "text", - "placeholders": {} - }, - "commandHint_myroomavatar": "הגדר את התמונה שלך לחדר זה (על ידי mxc-uri)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_myroomnick": "הגדר את שם התצוגה שלך עבור חדר זה", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "addToSpace": "הוסף לחלל", - "@addToSpace": {}, - "commandHint_unban": "בטל את החסימה של המשתמש הנתון מהחדר הזה", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "countParticipants": "{count} משתתפים", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "create": "צור", - "@create": { - "type": "text", - "placeholders": {} - }, - "createdTheChat": "{username} יצר את הצ'אט", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "currentlyActive": "פעיל כעת", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "כהה", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "dateWithoutYear": "{month}-{day}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "defaultPermissionLevel": "רמת הרשאת ברירת מחדל", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "מחק חשבון", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "מחק הודעה", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "deviceId": "מזהה מכשיר", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "התקנים", - "@devices": { - "type": "text", - "placeholders": {} - }, - "directChats": "צ'אטים ישירים", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "הורד קובץ", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "edit": "ערוך", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "ערוך את שם התצוגה", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "ערוך כינויים לחדר", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "אימוט כבר קיים!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "צ'אט ריק", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "encrypted": "מוצפן", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "enterAnEmailAddress": "הזן כתובת דואר אלקטרוני", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "enterYourHomeserver": "הזן את שרת הבית שלך", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "everythingReady": "הכל מוכן!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "fileName": "שם קובץ", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "fontSize": "גודל גופן", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "forward": "העבר", - "@forward": { - "type": "text", - "placeholders": {} - }, - "fromJoining": "מהצטרפות", - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "fromTheInvitation": "מההזמנה", - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "goToTheNewRoom": "עבור לחדר החדש", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "groupIsPublic": "הקבוצה ציבורית", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "groupWith": "קבוצה עם {displayname}", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "guestsAreForbidden": "אורחים אסורים", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "אורחים יכולים להצטרף", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "id": "מזהה", - "@id": { - "type": "text", - "placeholders": {} - }, - "identity": "זהות", - "@identity": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "משתמשים שהתעלמו מהם", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "incorrectPassphraseOrKey": "ביטוי סיסמה או מפתח שחזור שגויים", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "הזמן איש קשר", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "invited": "הזמין", - "@invited": { - "type": "text", - "placeholders": {} - }, - "invitedUser": "{username} הזמין את {targetName}", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "invitedUsersOnly": "משתמשים מוזמנים בלבד", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "inviteForMe": "הזמנה בשבילי", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "inviteText": "{username} הזמין אותך ל-FluffyChat.\n1. התקן את FluffyChat: https://fluffychat.im\n2. הירשם או היכנס\n3. פתח את קישור ההזמנה: {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "isTyping": "מקליד/ה…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "joinedTheChat": "{username} הצטרף לצ'אט", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "joinRoom": "הצטרף לחדר", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "kicked": "{username} בעט ב {targetName}", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickedAndBanned": "{username} בעט וחסם {targetName}", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickFromChat": "בעיטה מהצ'אט", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "lastActiveAgo": "פעילות אחרונה: {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "leftTheChat": "עזב את הצ'אט", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "loadingPleaseWait": "טוען אנא המתן.", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "loadMore": "טען עוד…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "locationDisabledNotice": "שירותי המיקום מושבתים. אנא הפעל אותם כדי לשתף את המיקום שלך.", - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "copy": "העתק", - "@copy": { - "type": "text", - "placeholders": {} - }, - "commandHint_send": "שלח טקסט", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandHint_op": "הגדרת רמת צריכת החשמל של המשתמש הנתון (ברירת מחדל: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_plain": "שלח טקסט לא מעוצב", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_react": "שלח תשובה כתגובה", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "containsUserName": "מכיל שם משתמש", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "createNewSpace": "חלל חדש", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "אפשר הצפנה", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "הזמן איש קשר אל {groupName}", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "dateWithYear": "{year}-{month}-{day}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "deactivateAccountWarning": "פעולה זו תשבית את חשבון המשתמש שלך. אי אפשר לבטל את זה! האם אתה בטוח?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "device": "מכשיר", - "@device": { - "type": "text", - "placeholders": {} - }, - "group": "קבוצה", - "@group": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "שם התצוגה השתנה", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "ערוך שרתים חסומים", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "עריכת אווטאר של חדר", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "{senderName} סיים את השיחה", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "groups": "קבוצות", - "@groups": { - "type": "text", - "placeholders": {} - }, - "enableEncryptionWarning": "לא תוכל לבטל את ההצפנה יותר. האם אתה בטוח?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "encryption": "הצפנה", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "errorObtainingLocation": "שגיאה בהשגת מיקום: {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "hasWithdrawnTheInvitationFor": "{username} ביטל את ההזמנה עבור {targetName}", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "hideRedactedEvents": "הסתר אירועים מצונזרים", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "encryptionNotEnabled": "ההצפנה אינה מופעלת", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "פוגעני ביותר", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "הסתר אירועים לא ידועים", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "loadCountMoreParticipants": "טען {count} משתתפים נוספים", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "homeserver": "שרת בית", - "@homeserver": {}, - "ignore": "התעלם", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "לחצתי על הקישור", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "leave": "לעזוב", - "@leave": { - "type": "text", - "placeholders": {} - }, - "license": "רשיון", - "@license": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "בהיר", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "delete": "מחיקה", - "@delete": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "לֹא פּוֹגֵעַ", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "configureChat": "קביעת תצורה של צ'אט", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "confirm": "לאשר", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "connect": "התחבר", - "@connect": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "איש הקשר הוזמן לקבוצה", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "מכיל שם תצוגה", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "התוכן דווח למנהלי השרת", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "הועתק ללוח הגזירים", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "commandInvalid": "הפקודה אינה חוקית", - "@commandInvalid": { - "type": "text" - }, - "commandMissing": "{command} אינו פקודה.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "compareEmojiMatch": "השווה וודא שהאימוג'י הבאים תואמים לאלו של המכשיר השני:", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "השווה וודא שהמספרים הבאים תואמים לאלה של המכשיר השני:", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "העתק ללוח", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "לא ניתן לפענח הודעה: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "help": "עזרה", - "@help": { - "type": "text", - "placeholders": {} - }, - "howOffensiveIsThisContent": "עד כמה התוכן הזה פוגעני?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "locationPermissionDeniedNotice": "הרשאת המיקום נדחתה. אנא אפשר את היכולת לשתף את מיקומך.", - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "login": "כניסה", - "@login": { - "type": "text", - "placeholders": {} - }, - "moderator": "מנחה", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "שים לב שאתה צריך Pantalaimon כדי להשתמש בהצפנה מקצה לקצה לעת עתה.", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "newChat": "צ'אט חדש", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "newVerificationRequest": "בקשת אימות חדשה!", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "next": "הבא", - "@next": { - "type": "text", - "placeholders": {} - }, - "no": "לא", - "@no": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "אין חיבור לשרת", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "אתה יכול להפעיל הצפנה רק כשהחדר כבר לא נגיש לציבור.", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "לא נמצאו חדרים…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "notifications": "התראות", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "numUsersTyping": "{count} משתמשים מקלידים…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "obtainingLocation": "משיג מיקום…", - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "onlineKeyBackupEnabled": "גיבוי מפתח מקוון מופעל", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "oopsPushError": "אופס! למרבה הצער, אירעה שגיאה בעת הגדרת התראות.", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "אופס, משהו השתבש…", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "פתח את האפליקציה לקריאת הודעות", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "oneClientLoggedOut": "אחד מהמכשירים שלך התנתק", - "@oneClientLoggedOut": {}, - "addAccount": "הוסף חשבון", - "@addAccount": {}, - "editBundlesForAccount": "ערוך חבילות עבור חשבון זה", - "@editBundlesForAccount": {}, - "participant": "משתתף", - "@participant": { - "type": "text", - "placeholders": {} - }, - "password": "סיסמה", - "@password": { - "type": "text", - "placeholders": {} - }, - "pleaseClickOnLink": "אנא לחץ על הקישור במייל ולאחר מכן המשך.", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "אנא הזן 4 ספרות או השאר ריק כדי להשבית את נעילת האפליקציה.", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "online": "מחובר/ת", - "@online": { - "type": "text", - "placeholders": {} - }, - "addToBundle": "הוסף לחבילה", - "@addToBundle": {}, - "passphraseOrKey": "ביטוי סיסמה או מפתח שחזור", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "שכחתי סיסמה", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "הסיסמה שונתה", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "passwordRecovery": "שחזור סיסמה", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "people": "אנשים", - "@people": { - "type": "text", - "placeholders": {} - }, - "pickImage": "בחר תמונה", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "play": "הפעל {fileName}", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "pleaseChoose": "אנא בחר", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "pleaseChooseAPasscode": "אנא בחר קוד גישה", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "נא הזן את הסיסמה שלך", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "אנא הזן את קוד הpin שלך", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "pin": "קוד pin", - "@pin": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "אנא הזן שם משתמש", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "הודעה חדשה ב-FluffyChat", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "noGoogleServicesWarning": "נראה שאין לך שירותי גוגל בטלפון שלך. זו החלטה טובה לפרטיות שלך! כדי לקבל התרעות ב- FluffyChat אנו ממליצים להשתמש https://microg.org/ או https://unifiedpush.org/.", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "noMatrixServer": "{server1} אינו שרת מטריקס, השתמש ב-{server2} במקום זאת?", - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "none": "ללא", - "@none": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "עדיין לא הוספת דרך לשחזר את הסיסמה שלך.", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "offensive": "פוגעני", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "notificationsEnabledForThisAccount": "התראות הופעלו עבור חשבון זה", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "bundleName": "שם החבילה", - "@bundleName": {}, - "offline": "לא מקוון", - "@offline": { - "type": "text", - "placeholders": {} - }, - "openVideoCamera": "פתח את המצלמה לסרטון", - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "removeFromBundle": "הסר מחבילה זו", - "@removeFromBundle": {}, - "enableMultiAccounts": "(בטא) אפשר ריבוי חשבונות במכשיר זה", - "@enableMultiAccounts": {}, - "openInMaps": "פתיחה במפות", - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "link": "קישור", - "@link": {}, - "serverRequiresEmail": "שרת זה צריך לאמת את כתובת הדואר האלקטרוני שלך לרישום.", - "@serverRequiresEmail": {}, - "logout": "יציאה", - "@logout": { - "type": "text", - "placeholders": {} - }, - "muteChat": "השתקת הצ'אט", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "scanQrCode": "סרוק קוד QR", - "@scanQrCode": {}, - "noPermission": "אין הרשאה", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "or": "או", - "@or": { - "type": "text", - "placeholders": {} - }, - "logInTo": "היכנס אל {homeserver}", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "memberChanges": "שינויים בחבר", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "mention": "הזכיר", - "@mention": { - "type": "text", - "placeholders": {} - }, - "messages": "הודעות", - "@messages": { - "type": "text", - "placeholders": {} - }, - "openCamera": "פתח מצלמה", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@widgetVideo": {}, - "@dismiss": {}, - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "@reportErrorDescription": {}, - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "@reply": { - "type": "text", - "placeholders": {} - }, - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "@unsupportedAndroidVersion": {}, - "@widgetJitsi": {}, - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "@messageType": {}, - "@indexedDbErrorLong": {}, - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "@startFirstChat": {}, - "@callingAccount": {}, - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@setColorTheme": {}, - "@nextAccount": {}, - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "@warning": { - "type": "text", - "placeholders": {} - }, - "@allSpaces": {}, - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "@user": {}, - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "@youAcceptedTheInvitation": {}, - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@banUserDescription": {}, - "@widgetEtherpad": {}, - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "@remove": { - "type": "text", - "placeholders": {} - }, - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "@unbanUserDescription": {}, - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "@youRejectedTheInvitation": {}, - "@otherCallingPermissions": {}, - "@messagesStyle": {}, - "@widgetUrlError": {}, - "@emailOrUsername": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "@enterSpace": {}, - "@encryptThisChat": {}, - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "@previousAccount": {}, - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "@reopenChat": {}, - "@pleaseEnterRecoveryKey": {}, - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "@widgetNameError": {}, - "@unpin": { - "type": "text", - "placeholders": {} - }, - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "@addWidget": {}, - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "@noKeyForThisMessage": {}, - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "@reason": { - "type": "text", - "placeholders": {} - }, - "@commandHint_markasgroup": {}, - "@hydrateTor": {}, - "@pushNotificationsNotAvailable": {}, - "@storeInAppleKeyChain": {}, - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "@hydrate": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "@sender": {}, - "@storeInAndroidKeystore": {}, - "@signInWithPassword": {}, - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "@makeAdminDescription": {}, - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "@saveKeyManuallyDescription": {}, - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "@whyIsThisMessageEncrypted": {}, - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@setChatDescription": {}, - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "@importFromZipFile": {}, - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "@dehydrateWarning": {}, - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "@noOtherDevicesFound": {}, - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@submit": { - "type": "text", - "placeholders": {} - }, - "@videoCallsBetaWarning": {}, - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@yes": { - "type": "text", - "placeholders": {} - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@username": { - "type": "text", - "placeholders": {} - }, - "@fileIsTooBigForServer": {}, - "@verified": { - "type": "text", - "placeholders": {} - }, - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "@callingPermissions": {}, - "@readUpToHere": {}, - "@start": {}, - "@register": { - "type": "text", - "placeholders": {} - }, - "@unlockOldMessages": {}, - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@recording": { - "type": "text", - "placeholders": {} - }, - "@optionalRedactReason": {}, - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "@dehydrate": {}, - "@send": { - "type": "text", - "placeholders": {} - }, - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "@sendAsText": { - "type": "text" - }, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "@experimentalVideoCalls": {}, - "@pleaseEnterRecoveryKeyDescription": {}, - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "@skip": { - "type": "text", - "placeholders": {} - }, - "@appearOnTopDetails": {}, - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "@enterRoom": {}, - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "@reportUser": {}, - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "@confirmEventUnpin": {}, - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@redactMessageDescription": {}, - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "@recoveryKey": {}, - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "@invalidInput": {}, - "@dehydrateTorLong": {}, - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "@doNotShowAgain": {}, - "@report": {}, - "@status": { - "type": "text", - "placeholders": {} - }, - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "@unverified": {}, - "@hideUnimportantStateEvents": {}, - "@screenSharingTitle": {}, - "@widgetCustom": {}, - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@addToSpaceDescription": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "@addChatDescription": {}, - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@publish": {}, - "@openLinkInBrowser": {}, - "@messageInfo": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "@foregroundServiceRunning": {}, - "@voiceCall": {}, - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "@noChatDescriptionYet": {}, - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "@confirmMatrixId": {}, - "@learnMore": {}, - "@you": { - "type": "text", - "placeholders": {} - }, - "@notAnImage": {}, - "@users": {}, - "@openGallery": {}, - "@chatDescriptionHasBeenChanged": {}, - "@search": { - "type": "text", - "placeholders": {} - }, - "@newGroup": {}, - "@dehydrateTor": {}, - "@removeFromSpace": {}, - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "@roomUpgradeDescription": {}, - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "@pleaseEnterANumber": {}, - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "@profileNotFound": {}, - "@jump": {}, - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "@sorryThatsNotPossible": {}, - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "@shareInviteLink": {}, - "@commandHint_markasdm": {}, - "@recoveryKeyLost": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@deviceKeys": {}, - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "@settings": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@youJoinedTheChat": {}, - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "@security": { - "type": "text", - "placeholders": {} - }, - "@markAsRead": {}, - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "@widgetName": {}, - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@errorAddingWidget": {}, - "@commandHint_hug": {}, - "@replace": {}, - "@reject": { - "type": "text", - "placeholders": {} - }, - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "@newSpace": {}, - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "@emojis": {}, - "@share": { - "type": "text", - "placeholders": {} - }, - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@privacy": { - "type": "text", - "placeholders": {} - }, - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "@hydrateTorLong": {}, - "@time": {}, - "@custom": {}, - "@noBackupWarning": {}, - "@verify": { - "type": "text", - "placeholders": {} - }, - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "@storeInSecureStorageDescription": {}, - "@openChat": {}, - "@kickUserDescription": {}, - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "@importNow": {}, - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "@pinMessage": {}, - "@invite": {}, - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "@indexedDbErrorTitle": {}, - "@unsupportedAndroidVersionLong": {}, - "@storeSecurlyOnThisDevice": {}, - "@ok": { - "type": "text", - "placeholders": {} - }, - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "@screenSharingDetail": {}, - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "@placeCall": {} -} \ No newline at end of file + "@@last_modified": "2021-08-14 12:41:10.036931", + "about": "אודות", + "@about": { + "type": "text", + "placeholders": {} + }, + "accept": "קבל", + "@accept": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "{username} קיבל את ההזמנה", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "account": "חשבון", + "@account": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "{username} הפעיל הצפנה מקצה לקצה", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "admin": "מנהל", + "@admin": { + "type": "text", + "placeholders": {} + }, + "alias": "כינוי", + "@alias": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "{senderName} ענה לשיחה", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "anyoneCanJoin": "כל אחד יכול להצטרף", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "archive": "ארכיון", + "@archive": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "האם משתמשים אורחים מורשים להצטרף", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "האם אתה בטוח?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "askSSSSSign": "כדי שתוכל לחתום על משתמש אחר , הזן את הסיסמה שלך או את מפתח השחזור.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "לקבל בקשת אימות זו מ- {username}?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changePassword": "שנה סיסמא", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "appLock": "נעילת אפליקציה", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "cancel": "ביטול", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "addEmail": "הוסף מייל", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "all": "הכל", + "@all": { + "type": "text", + "placeholders": {} + }, + "allChats": "כל הצ'אטים", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "banned": "חסום", + "@banned": { + "type": "text", + "placeholders": {} + }, + "sendOnEnter": "שלח בכניסה", + "@sendOnEnter": {}, + "badServerLoginTypesException": "שרת הבית תומך בסוגי הכניסה:\n{serverVersions}\nאבל אפליקציה זו תומכת רק ב:\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "changedTheGuestAccessRulesTo": "{username} שינה את כללי הגישה לאורחים ל: {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRules": "{username} שינה את כללי ההצטרפות", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatNameTo": "{username} שינה את שם הצ'אט ל: '{chatname}'", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changedTheRoomInvitationLink": "{username} שינה את קישור ההזמנה", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "repeatPassword": "כתוב שוב את הסיסמה", + "@repeatPassword": {}, + "areYouSureYouWantToLogout": "האם אתה בטוח שברצונך לצאת?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "chat": "צ׳אט", + "@chat": { + "type": "text", + "placeholders": {} + }, + "autoplayImages": "הפעל אוטומטית מדבקות ואנימציות מונפשים", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "badServerVersionsException": "שרת הבית תומך בגרסאות:\n{serverVersions}\nאבל האפליקציה הזו תומכת רק ב-{supportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "banFromChat": "צאט חסום", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "{username} חסם את {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "blockDevice": "חסום מכשיר", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "blocked": "חסום", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "botMessages": "הודעות בוט", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "cantOpenUri": "לא ניתן לפתוח את ה-URI {uri}", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "changeDeviceName": "שנה את שם המכשיר", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "changedTheChatAvatar": "{username} שינה את האווטאר של הצ'אט", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatDescriptionTo": "{username} שינה את תיאור הצ'אט ל: '{description}'", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "changedTheChatPermissions": "{username} שינה את הרשאות הצ'אט", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "{username} שינה את שם התצוגה שלו ל: '{displayname}'", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRules": "{username} שינה את כללי הגישה לאורחים", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibility": "{username} שינה את נראות ההיסטוריה", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibilityTo": "{username} שינה את נראות ההיסטוריה ל: {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRulesTo": "{username} שינה את כללי ההצטרפות ל: {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheProfileAvatar": "{username} שינה את האווטאר שלו", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "{username} שינה את כינוי החדר", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changeTheHomeserver": "שנה את שרת הבית", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "שנה את הסגנון שלך", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "שנה את שם הקבוצה", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "changeYourAvatar": "שינוי האווטאר שלך", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "channelCorruptedDecryptError": "ההצפנה נפגמה", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "yourChatBackupHasBeenSetUp": "גיבוי הצ'אט שלך הוגדר.", + "@yourChatBackupHasBeenSetUp": {}, + "chatBackup": "גיבוי צ'אט", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "commandHint_ban": "חסום את המשתמש הנתון מהחדר הזה", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_clearcache": "נקה מטמון", + "@commandHint_clearcache": { + "type": "text", + "description": "Usage hint for the command /clearcache" + }, + "commandHint_create": "צור צ'אט קבוצתי ריק\nהשתמש ב--no-encryption כדי להשבית את ההצפנה", + "@commandHint_create": { + "type": "text", + "description": "Usage hint for the command /create" + }, + "commandHint_discardsession": "התעלם מהסשן", + "@commandHint_discardsession": { + "type": "text", + "description": "Usage hint for the command /discardsession" + }, + "commandHint_dm": "התחל צ'אט ישיר\nהשתמש ב--no-encryption כדי להשבית את ההצפנה", + "@commandHint_dm": { + "type": "text", + "description": "Usage hint for the command /dm" + }, + "commandHint_html": "שלח טקסט בתבנית HTML", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_invite": "הזמן את המשתמש הנתון לחדר זה", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "commandHint_join": "הצטרף לחדר הנתון", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_kick": "הסר את המשתמש הנתון מהחדר הזה", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_leave": "עזוב את החדר הזה", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_me": "תאר את עצמך", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "chatDetails": "פרטי צ'אט", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chatBackupDescription": "גיבוי הצ'אט שלך מאובטח באמצעות מפתח אבטחה. אנא וודא שאתה לא מאבד אותו.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "chatHasBeenAddedToThisSpace": "צ'אט נוסף למרחב הזה", + "@chatHasBeenAddedToThisSpace": {}, + "chats": "צ'אטים", + "@chats": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "בחר סיסמה חזקה", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "clearArchive": "נקה ארכיון", + "@clearArchive": {}, + "close": "סגור", + "@close": { + "type": "text", + "placeholders": {} + }, + "commandHint_myroomavatar": "הגדר את התמונה שלך לחדר זה (על ידי mxc-uri)", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_myroomnick": "הגדר את שם התצוגה שלך עבור חדר זה", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "addToSpace": "הוסף לחלל", + "@addToSpace": {}, + "commandHint_unban": "בטל את החסימה של המשתמש הנתון מהחדר הזה", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "countParticipants": "{count} משתתפים", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "create": "צור", + "@create": { + "type": "text", + "placeholders": {} + }, + "createdTheChat": "{username} יצר את הצ'אט", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "currentlyActive": "פעיל כעת", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "כהה", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "dateWithoutYear": "{month}-{day}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "defaultPermissionLevel": "רמת הרשאת ברירת מחדל", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "מחק חשבון", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "מחק הודעה", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "deviceId": "מזהה מכשיר", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "devices": "התקנים", + "@devices": { + "type": "text", + "placeholders": {} + }, + "directChats": "צ'אטים ישירים", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "הורד קובץ", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "edit": "ערוך", + "@edit": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "ערוך את שם התצוגה", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "ערוך כינויים לחדר", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "אימוט כבר קיים!", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "emptyChat": "צ'אט ריק", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "encrypted": "מוצפן", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "enterAnEmailAddress": "הזן כתובת דואר אלקטרוני", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "enterYourHomeserver": "הזן את שרת הבית שלך", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "everythingReady": "הכל מוכן!", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "fileName": "שם קובץ", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "fontSize": "גודל גופן", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "forward": "העבר", + "@forward": { + "type": "text", + "placeholders": {} + }, + "fromJoining": "מהצטרפות", + "@fromJoining": { + "type": "text", + "placeholders": {} + }, + "fromTheInvitation": "מההזמנה", + "@fromTheInvitation": { + "type": "text", + "placeholders": {} + }, + "goToTheNewRoom": "עבור לחדר החדש", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "groupIsPublic": "הקבוצה ציבורית", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "groupWith": "קבוצה עם {displayname}", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "guestsAreForbidden": "אורחים אסורים", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "אורחים יכולים להצטרף", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "id": "מזהה", + "@id": { + "type": "text", + "placeholders": {} + }, + "identity": "זהות", + "@identity": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "משתמשים שהתעלמו מהם", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "incorrectPassphraseOrKey": "ביטוי סיסמה או מפתח שחזור שגויים", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "הזמן איש קשר", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "invited": "הזמין", + "@invited": { + "type": "text", + "placeholders": {} + }, + "invitedUser": "{username} הזמין את {targetName}", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "invitedUsersOnly": "משתמשים מוזמנים בלבד", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "inviteForMe": "הזמנה בשבילי", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "inviteText": "{username} הזמין אותך ל-FluffyChat.\n1. התקן את FluffyChat: https://fluffychat.im\n2. הירשם או היכנס\n3. פתח את קישור ההזמנה: {link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "isTyping": "מקליד/ה…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "joinedTheChat": "{username} הצטרף לצ'אט", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "joinRoom": "הצטרף לחדר", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "kicked": "{username} בעט ב {targetName}", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickedAndBanned": "{username} בעט וחסם {targetName}", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickFromChat": "בעיטה מהצ'אט", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "lastActiveAgo": "פעילות אחרונה: {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "leftTheChat": "עזב את הצ'אט", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "loadingPleaseWait": "טוען אנא המתן.", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "loadMore": "טען עוד…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "locationDisabledNotice": "שירותי המיקום מושבתים. אנא הפעל אותם כדי לשתף את המיקום שלך.", + "@locationDisabledNotice": { + "type": "text", + "placeholders": {} + }, + "copy": "העתק", + "@copy": { + "type": "text", + "placeholders": {} + }, + "commandHint_send": "שלח טקסט", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "commandHint_op": "הגדרת רמת צריכת החשמל של המשתמש הנתון (ברירת מחדל: 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_plain": "שלח טקסט לא מעוצב", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_react": "שלח תשובה כתגובה", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "containsUserName": "מכיל שם משתמש", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "createNewSpace": "חלל חדש", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "אפשר הצפנה", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "הזמן איש קשר אל {groupName}", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "dateWithYear": "{year}-{month}-{day}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "deactivateAccountWarning": "פעולה זו תשבית את חשבון המשתמש שלך. אי אפשר לבטל את זה! האם אתה בטוח?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "device": "מכשיר", + "@device": { + "type": "text", + "placeholders": {} + }, + "group": "קבוצה", + "@group": { + "type": "text", + "placeholders": {} + }, + "displaynameHasBeenChanged": "שם התצוגה השתנה", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "ערוך שרתים חסומים", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "עריכת אווטאר של חדר", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "{senderName} סיים את השיחה", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "groups": "קבוצות", + "@groups": { + "type": "text", + "placeholders": {} + }, + "enableEncryptionWarning": "לא תוכל לבטל את ההצפנה יותר. האם אתה בטוח?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "encryption": "הצפנה", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "errorObtainingLocation": "שגיאה בהשגת מיקום: {error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "hasWithdrawnTheInvitationFor": "{username} ביטל את ההזמנה עבור {targetName}", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "hideRedactedEvents": "הסתר אירועים מצונזרים", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "encryptionNotEnabled": "ההצפנה אינה מופעלת", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "extremeOffensive": "פוגעני ביותר", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "הסתר אירועים לא ידועים", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "loadCountMoreParticipants": "טען {count} משתתפים נוספים", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "homeserver": "שרת בית", + "@homeserver": {}, + "ignore": "התעלם", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "לחצתי על הקישור", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "leave": "לעזוב", + "@leave": { + "type": "text", + "placeholders": {} + }, + "license": "רשיון", + "@license": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "בהיר", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "delete": "מחיקה", + "@delete": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "לֹא פּוֹגֵעַ", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "configureChat": "קביעת תצורה של צ'אט", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "confirm": "לאשר", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "connect": "התחבר", + "@connect": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "איש הקשר הוזמן לקבוצה", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "מכיל שם תצוגה", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "התוכן דווח למנהלי השרת", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "הועתק ללוח הגזירים", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "commandInvalid": "הפקודה אינה חוקית", + "@commandInvalid": { + "type": "text" + }, + "commandMissing": "{command} אינו פקודה.", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "compareEmojiMatch": "השווה וודא שהאימוג'י הבאים תואמים לאלו של המכשיר השני:", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "השווה וודא שהמספרים הבאים תואמים לאלה של המכשיר השני:", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "העתק ללוח", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "לא ניתן לפענח הודעה: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "help": "עזרה", + "@help": { + "type": "text", + "placeholders": {} + }, + "howOffensiveIsThisContent": "עד כמה התוכן הזה פוגעני?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "locationPermissionDeniedNotice": "הרשאת המיקום נדחתה. אנא אפשר את היכולת לשתף את מיקומך.", + "@locationPermissionDeniedNotice": { + "type": "text", + "placeholders": {} + }, + "login": "כניסה", + "@login": { + "type": "text", + "placeholders": {} + }, + "moderator": "מנחה", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "שים לב שאתה צריך Pantalaimon כדי להשתמש בהצפנה מקצה לקצה לעת עתה.", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "newChat": "צ'אט חדש", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "newVerificationRequest": "בקשת אימות חדשה!", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "next": "הבא", + "@next": { + "type": "text", + "placeholders": {} + }, + "no": "לא", + "@no": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "אין חיבור לשרת", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "אתה יכול להפעיל הצפנה רק כשהחדר כבר לא נגיש לציבור.", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "לא נמצאו חדרים…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "notifications": "התראות", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "numUsersTyping": "{count} משתמשים מקלידים…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "obtainingLocation": "משיג מיקום…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "onlineKeyBackupEnabled": "גיבוי מפתח מקוון מופעל", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "אופס! למרבה הצער, אירעה שגיאה בעת הגדרת התראות.", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "אופס, משהו השתבש…", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "פתח את האפליקציה לקריאת הודעות", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "oneClientLoggedOut": "אחד מהמכשירים שלך התנתק", + "@oneClientLoggedOut": {}, + "addAccount": "הוסף חשבון", + "@addAccount": {}, + "editBundlesForAccount": "ערוך חבילות עבור חשבון זה", + "@editBundlesForAccount": {}, + "participant": "משתתף", + "@participant": { + "type": "text", + "placeholders": {} + }, + "password": "סיסמה", + "@password": { + "type": "text", + "placeholders": {} + }, + "pleaseClickOnLink": "אנא לחץ על הקישור במייל ולאחר מכן המשך.", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "אנא הזן 4 ספרות או השאר ריק כדי להשבית את נעילת האפליקציה.", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "online": "מחובר/ת", + "@online": { + "type": "text", + "placeholders": {} + }, + "addToBundle": "הוסף לחבילה", + "@addToBundle": {}, + "passphraseOrKey": "ביטוי סיסמה או מפתח שחזור", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "שכחתי סיסמה", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "הסיסמה שונתה", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "passwordRecovery": "שחזור סיסמה", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "people": "אנשים", + "@people": { + "type": "text", + "placeholders": {} + }, + "pickImage": "בחר תמונה", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "play": "הפעל {fileName}", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "pleaseChoose": "אנא בחר", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "pleaseChooseAPasscode": "אנא בחר קוד גישה", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "נא הזן את הסיסמה שלך", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "אנא הזן את קוד הpin שלך", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "pin": "קוד pin", + "@pin": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "אנא הזן שם משתמש", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "הודעה חדשה ב-FluffyChat", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "noGoogleServicesWarning": "נראה שאין לך שירותי גוגל בטלפון שלך. זו החלטה טובה לפרטיות שלך! כדי לקבל התרעות ב- FluffyChat אנו ממליצים להשתמש https://microg.org/ או https://unifiedpush.org/.", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "noMatrixServer": "{server1} אינו שרת מטריקס, השתמש ב-{server2} במקום זאת?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "none": "ללא", + "@none": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "עדיין לא הוספת דרך לשחזר את הסיסמה שלך.", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "offensive": "פוגעני", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "notificationsEnabledForThisAccount": "התראות הופעלו עבור חשבון זה", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "bundleName": "שם החבילה", + "@bundleName": {}, + "offline": "לא מקוון", + "@offline": { + "type": "text", + "placeholders": {} + }, + "openVideoCamera": "פתח את המצלמה לסרטון", + "@openVideoCamera": { + "type": "text", + "placeholders": {} + }, + "removeFromBundle": "הסר מחבילה זו", + "@removeFromBundle": {}, + "enableMultiAccounts": "(בטא) אפשר ריבוי חשבונות במכשיר זה", + "@enableMultiAccounts": {}, + "openInMaps": "פתיחה במפות", + "@openInMaps": { + "type": "text", + "placeholders": {} + }, + "link": "קישור", + "@link": {}, + "serverRequiresEmail": "שרת זה צריך לאמת את כתובת הדואר האלקטרוני שלך לרישום.", + "@serverRequiresEmail": {}, + "logout": "יציאה", + "@logout": { + "type": "text", + "placeholders": {} + }, + "muteChat": "השתקת הצ'אט", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "scanQrCode": "סרוק קוד QR", + "@scanQrCode": {}, + "noPermission": "אין הרשאה", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "or": "או", + "@or": { + "type": "text", + "placeholders": {} + }, + "logInTo": "היכנס אל {homeserver}", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "memberChanges": "שינויים בחבר", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "mention": "הזכיר", + "@mention": { + "type": "text", + "placeholders": {} + }, + "messages": "הודעות", + "@messages": { + "type": "text", + "placeholders": {} + }, + "openCamera": "פתח מצלמה", + "@openCamera": { + "type": "text", + "placeholders": {} + } +} diff --git a/assets/l10n/intl_hr.arb b/assets/l10n/intl_hr.arb index dcf927e7e..3d6c84730 100644 --- a/assets/l10n/intl_hr.arb +++ b/assets/l10n/intl_hr.arb @@ -914,7 +914,7 @@ "targetName": {} } }, - "kickedAndBanned": "🙅 {username} je izbacio/la i isključio/la {targetName}", + "kickedAndBanned": "🙅 {username} je izbacio/la i blokirao/la {targetName}", "@kickedAndBanned": { "type": "text", "placeholders": { @@ -949,7 +949,7 @@ "type": "text", "placeholders": {} }, - "lightTheme": "Svjetla", + "lightTheme": "Svijetla", "@lightTheme": { "type": "text", "placeholders": {} @@ -2029,7 +2029,7 @@ "@recoveryKey": {}, "recoveryKeyLost": "Izgubio/la si ključ za obnavljanje?", "@recoveryKeyLost": {}, - "youKickedAndBanned": "🙅 Izbacio/la si i isključio/la korisnika {user}", + "youKickedAndBanned": "🙅 Izbacio/la si i blokirao/la korisnika {user}", "@youKickedAndBanned": { "placeholders": { "user": {} @@ -2449,5 +2449,268 @@ "discover": "Otkrij", "@discover": {}, "formattedMessagesDescription": "Prikaži formatirani sadržaj poruke poput podebljanog teksta koristeći markdown.", - "@formattedMessagesDescription": {} + "@formattedMessagesDescription": {}, + "nothingFound": "Ništa nije pronađeno...", + "@nothingFound": {}, + "select": "Odaberi", + "@select": {}, + "newPassword": "Nova lozinka", + "@newPassword": {}, + "unbanUserDescription": "Korisnik će se ponovo moći pridružiti razgovoru ako pokuša.", + "@unbanUserDescription": {}, + "publicSpaces": "Javni prostori", + "@publicSpaces": {}, + "subspace": "Podprostori", + "@subspace": {}, + "decline": "Odbij", + "@decline": {}, + "thisDevice": "Ovaj uređaj:", + "@thisDevice": {}, + "presenceStyle": "Prisutnost:", + "@presenceStyle": { + "type": "text", + "placeholders": {} + }, + "presencesToggle": "Prikaži poruke stanja od drugih korisnika", + "@presencesToggle": { + "type": "text", + "placeholders": {} + }, + "noPublicLinkHasBeenCreatedYet": "Još nije stvorena nijedna javna poveznica", + "@noPublicLinkHasBeenCreatedYet": {}, + "hidePresences": "Sakriti popis stanja?", + "@hidePresences": {}, + "pleaseEnterYourCurrentPassword": "Upiši svoju trenutačnu lozinku", + "@pleaseEnterYourCurrentPassword": {}, + "publicLink": "Javna poveznica", + "@publicLink": {}, + "passwordIsWrong": "Tvoja upisana lozinka je kriva", + "@passwordIsWrong": {}, + "initAppError": "Dogodila se greška prilikom inicijaliziranja aplikacije", + "@initAppError": {}, + "hideRedactedMessagesBody": "Ako netko redigira poruku, ta poruka više neće biti vidljiva u razgovoru.", + "@hideRedactedMessagesBody": {}, + "kickUserDescription": "Korisnik je izbačen iz razgovora, ali nije blokiran. U javnim razgovorima se korisnik može ponovo pridružiti u bilo kojem trenutku.", + "@kickUserDescription": {}, + "addChatOrSubSpace": "Dodaj razgovor ili podpodručje", + "@addChatOrSubSpace": {}, + "appLockDescription": "Zaključaj aplikaciju kada je ne koristiš s PIN kodom", + "@appLockDescription": {}, + "globalChatId": "Globalni ID razgovora", + "@globalChatId": {}, + "hideRedactedMessages": "Sakrij redigirane poruke", + "@hideRedactedMessages": {}, + "hideInvalidOrUnknownMessageFormats": "Sakrij nevažeće ili nepoznate formate poruka", + "@hideInvalidOrUnknownMessageFormats": {}, + "overview": "Pregled", + "@overview": {}, + "notifyMeFor": "Obavijesit me za", + "@notifyMeFor": {}, + "passwordRecoverySettings": "Postavke za obnavljanje lozinke", + "@passwordRecoverySettings": {}, + "hideMemberChangesInPublicChats": "Sakrij promjene članova u javnim razgovorima", + "@hideMemberChangesInPublicChats": {}, + "youInvitedToBy": "📩 Pozvan/a si putem poveznice na:\n{alias}", + "@youInvitedToBy": { + "placeholders": { + "alias": {} + } + }, + "usersMustKnock": "Korisnici moraju pokucati", + "@usersMustKnock": {}, + "noOneCanJoin": "Nitko se ne može pridružiti", + "@noOneCanJoin": {}, + "userWouldLikeToChangeTheChat": "{user} se želi pridružiti razgovoru.", + "@userWouldLikeToChangeTheChat": { + "placeholders": { + "user": {} + } + }, + "knock": "Pokucaj", + "@knock": {}, + "knocking": "Kucanje", + "@knocking": {}, + "chatCanBeDiscoveredViaSearchOnServer": "Razgovor se može otkriti pretraživanjem servera {server}", + "@chatCanBeDiscoveredViaSearchOnServer": { + "type": "text", + "placeholders": { + "server": {} + } + }, + "searchForUsers": "Traži @users...", + "@searchForUsers": {}, + "pleaseChooseAStrongPassword": "Odaberi snažnu lozinku", + "@pleaseChooseAStrongPassword": {}, + "joinSpace": "Pridruži se prostoru", + "@joinSpace": {}, + "publicChatAddresses": "Adrese javnih razgovora", + "@publicChatAddresses": {}, + "createNewAddress": "Stvori novu adresu", + "@createNewAddress": {}, + "userRole": "Korisnička uloga", + "@userRole": {}, + "verifyOtherUser": "🔐 Potvrdi drugog korisnika", + "@verifyOtherUser": {}, + "sendTypingNotificationsDescription": "Drugi sudionici u razgovoru mogu vidjeti kada pišeš novu poruku.", + "@sendTypingNotificationsDescription": {}, + "sendReadReceiptsDescription": "Drugi sudionici u raygovoru mogu vidjeti kada pročitaš poruku.", + "@sendReadReceiptsDescription": {}, + "searchIn": "Traži u razgovoru „{chat}”...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "searchMore": "Traži više...", + "@searchMore": {}, + "gallery": "Galerija", + "@gallery": {}, + "files": "Datoteke", + "@files": {}, + "verifyOtherDevice": "🔐 Potvrdi drugi uređaj", + "@verifyOtherDevice": {}, + "unreadChatsInApp": "{appname}: Nroj nepročitanih razgovora: {unread}", + "@unreadChatsInApp": { + "type": "text", + "placeholders": { + "appname": {}, + "unread": {} + } + }, + "commandHint_ignore": "Zanemari navedeni matrix ID", + "@commandHint_ignore": {}, + "blockListDescription": "Možeš blokirati korisnike koji te ometaju. Nećeš moći primati poruke ili pozivnice za sobe od korisnika koji se nalaze u tvom osobnom popisu blokiranih.", + "@blockListDescription": {}, + "isReadyForKeyVerification": "{sender} je spreman/na za potvrđivanje ključa", + "@isReadyForKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "banUserDescription": "Korisnik će biti isključen iz razgovora i moći će ponovo prisustvovati razgovoru kad ga se deblokira.", + "@banUserDescription": {}, + "sessionLostBody": "Tvoja je sesija izgubljena. Prijavi ovu grešku programerima na {url}. Poruka o grešci glasi: {error}", + "@sessionLostBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "completedKeyVerification": "{sender} je dovršio/la potvrđivanje ključa", + "@completedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "archiveRoomDescription": "Razgovor će se premjestiti u arhivu. Drugi korisnici će moći vidjeti da si napustio/la razgovor.", + "@archiveRoomDescription": {}, + "removeDevicesDescription": "Bit ćeš odjavljen/a s ovog uređaja i više nećeš moći primati poruke.", + "@removeDevicesDescription": {}, + "noUsersFoundWithQuery": "Nažalost nije pronađen nijedan korisnik s „{query}”. Provjeri točnost upisa.", + "@noUsersFoundWithQuery": { + "type": "text", + "placeholders": { + "query": {} + } + }, + "restoreSessionBody": "Aplikacija sada pokušava obnoviti tvoju sesiju iz sigurnosne kopije. Prijavi ovu grešku programerima na {url}. Poruka o grešci glasi: {error}", + "@restoreSessionBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "requestedKeyVerification": "{sender} je zatražio/la potvrđivanje ključa", + "@requestedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "restricted": "Ograničeni", + "@restricted": {}, + "roomUpgradeDescription": "Razgovor će se tada ponovo stvoriti s novom verzijom sobe. Svi sudionici će biti obaviješteni da se moraju prebaciti na novi razgovor. Više o verzijama soba možeš saznati na https://spec.matrix.org/latest/rooms/", + "@roomUpgradeDescription": {}, + "noGoogleServicesWarning": "Čini se da Firebase Cloud Messaging nije dostupan na tvom uređaju. Za daljnje primanje push obavijesti, preporučujemo da instaliraš ntfy. S ntfy ili drugim pružateljem usluge Unified Push možeš primati push obavijesti na podatkovno siguran način. Ntfy možeš preuzeti s PlayStorea ili s F-Droida.", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "verifyOtherDeviceDescription": "Kada potvrdiš jedan drugi uređaj, ti uređaji mogu razmjenjivati ključeve, povećavajući tvoju ukupnu sigurnost. 💪 Kada pokreneš provjeru, pojavit će se skočni prozor u aplikaciji na oba uređaja. Tamo ćeš tada vidjeti niz emojija ili brojeve koje moraš međusobno usporediti. Najbolje je imati oba uređaja pri ruci prije nego što započneš provjeru. 🤳", + "@verifyOtherDeviceDescription": {}, + "verifyOtherUserDescription": "Ako potvrdiš jednog drugog korisnika, možeš biti siguran/na da znaš kome zapravo pišeš. 💪\n\nKada pokreneš provjeru, vi i drugi korisnik vidjet ćete skočni prozor u aplikaciji. Tamo ćeš tada vidjeti niz emojija ili brojeve koje morate međusobno usporediti.\n\nNajbolji način za to je da se nađete zajedno ili započnete videopoziv. 👭", + "@verifyOtherUserDescription": {}, + "knockRestricted": "Pokucaj na ograničene sobe", + "@knockRestricted": {}, + "hideMemberChangesInPublicChatsBody": "Za bolju čitljivosti, na vremenskoj traci razgovora nemoj prikazivati kad se netko pridruži ili napusti javni razgovor.", + "@hideMemberChangesInPublicChatsBody": {}, + "makeAdminDescription": "Nakon postavljanja ovog korisnika kao administratora, to možda nećeš moći poništiti jer će on tada imati iste dozvole kao i ti.", + "@makeAdminDescription": {}, + "leaveEmptyToClearStatus": "Ostavi prazno za brisanje tvog stanja.", + "@leaveEmptyToClearStatus": {}, + "forwardMessageTo": "Proslijediti poruku u sobu {roomName}?", + "@forwardMessageTo": { + "type": "text", + "placeholders": { + "roomName": {} + } + }, + "minimumPowerLevel": "{level} je najmanja razina prava.", + "@minimumPowerLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "databaseBuildErrorBody": "Nije moguće izgraditi SQlite bazu podataka. Aplikacija za sada pokušava koristiti staru bazu podataka. Prijavi ovu grešku programerima na {url}. Poruka o grešci glasi: {error}", + "@databaseBuildErrorBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "sendReadReceipts": "Šalji potvrde o čitanju", + "@sendReadReceipts": {}, + "acceptedKeyVerification": "{sender} je prihvatio/la potvrđivanje ključa", + "@acceptedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "canceledKeyVerification": "{sender} je prekinuo/la potvrđivanje ključa", + "@canceledKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "startedKeyVerification": "{sender} je pokrenuo/la potvrđivanje ključa", + "@startedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "commandHint_unignore": "Poništi zanemarivanje navedenog matrix ID-a", + "@commandHint_unignore": {}, + "noDatabaseEncryption": "Šifriranje baze podataka nije podržano na ovoj platformi", + "@noDatabaseEncryption": {}, + "thereAreCountUsersBlocked": "Broj trenutačno blokiranih korisnika: {count}.", + "@thereAreCountUsersBlocked": { + "type": "text", + "count": {} + }, + "swipeRightToLeftToReply": "Za odgovaranje povuci prstom zdesna ulijevo", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "true", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + } } diff --git a/assets/l10n/intl_hu.arb b/assets/l10n/intl_hu.arb index daae996ce..185a04816 100644 --- a/assets/l10n/intl_hu.arb +++ b/assets/l10n/intl_hu.arb @@ -2245,7 +2245,7 @@ }, "addChatDescription": "Chat leírás hozzáadása...", "@addChatDescription": {}, - "hasKnocked": "{user} kopogott", + "hasKnocked": "🚪 {user} bekopogott", "@hasKnocked": { "placeholders": { "user": {} @@ -2419,7 +2419,7 @@ "@screenSharingDetail": {}, "placeCall": "Tér hívás", "@placeCall": {}, - "block": "blokkolás", + "block": "Blokkolás", "@block": {}, "blockedUsers": "Blokkolt felhasználók", "@blockedUsers": {}, @@ -2664,5 +2664,47 @@ "appname": {}, "unread": {} } - } + }, + "searchIn": "Keresés a csevegésben \"{chat}\"...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "files": "Fájlok", + "@files": {}, + "commandHint_unignore": "Adott matrix ID figyelembe vétele", + "@commandHint_unignore": {}, + "restricted": "Korlátozott", + "@restricted": {}, + "knockRestricted": "Kopogás korlátozva", + "@knockRestricted": {}, + "globalChatId": "Globális csevegő azonosító", + "@globalChatId": {}, + "hideRedactedMessages": "Szerkesztett üzenetek elrejtése", + "@hideRedactedMessages": {}, + "hideRedactedMessagesBody": "Ha valaki szerkeszti az üzenetét, ez az üzenet nem jelenik meg a csevegés során.", + "@hideRedactedMessagesBody": {}, + "hideMemberChangesInPublicChats": "Tag változások elrejtése a publikus csevegésben", + "@hideMemberChangesInPublicChats": {}, + "knocking": "Bekopogás", + "@knocking": {}, + "usersMustKnock": "A felhasználóknak be kell kopogniuk", + "@usersMustKnock": {}, + "knock": "Kopogás", + "@knock": {}, + "minimumPowerLevel": "{level} a minimum szint.", + "@minimumPowerLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "searchMore": "További keresés...", + "@searchMore": {}, + "gallery": "Galéria", + "@gallery": {}, + "commandHint_ignore": "Adott matrix ID figyelmen kívül hagyása", + "@commandHint_ignore": {} } diff --git a/assets/l10n/intl_id.arb b/assets/l10n/intl_id.arb index 34f821c5e..aa4879c95 100644 --- a/assets/l10n/intl_id.arb +++ b/assets/l10n/intl_id.arb @@ -324,7 +324,7 @@ "type": "text", "placeholders": {} }, - "edit": "Edit", + "edit": "Sunting", "@edit": { "type": "text", "placeholders": {} @@ -2323,7 +2323,7 @@ "@sendTypingNotifications": {}, "createGroup": "Buat grup", "@createGroup": {}, - "inviteContactToGroupQuestion": "Apakah kamu ingin mengundang {contact} ke chat \"{groupName}\"?", + "inviteContactToGroupQuestion": "Apakah kamu ingin mengundang {contact} ke obrolan \"{groupName}\"?", "@inviteContactToGroupQuestion": {}, "tryAgain": "Coba ulang", "@tryAgain": {}, @@ -2335,15 +2335,15 @@ "@setTheme": {}, "invalidServerName": "Nama server tidak valid", "@invalidServerName": {}, - "addChatDescription": "Tambahkan deskripsi chat...", + "addChatDescription": "Tambahkan deskripsi obrolan...", "@addChatDescription": {}, - "chatPermissions": "Perizinan chat", + "chatPermissions": "Perizinan obrolan", "@chatPermissions": {}, - "chatDescription": "Deskripsi chat", + "chatDescription": "Deskripsi obrolan", "@chatDescription": {}, - "chatDescriptionHasBeenChanged": "Deskripsi chat diubah", + "chatDescriptionHasBeenChanged": "Deskripsi obrolan diubah", "@chatDescriptionHasBeenChanged": {}, - "noChatDescriptionYet": "Deskripsi chat belum dibuat.", + "noChatDescriptionYet": "Deskripsi obrolan belum dibuat.", "@noChatDescriptionYet": {}, "redactMessageDescription": "Pesan akan dihilangkan untuk semua anggota dalam percakapan ini. Ini tidak dapat diurungkan.", "@redactMessageDescription": {}, @@ -2366,7 +2366,7 @@ "reason": {} } }, - "setChatDescription": "Lihat deskripsi chat", + "setChatDescription": "Lihat deskripsi obrolan", "@setChatDescription": {}, "profileNotFound": "Pengguna ini tidak dapat ditemukan di server. Mungkin ada masalah koneksi atau penggunanya tidak ada.", "@profileNotFound": {}, @@ -2688,5 +2688,28 @@ "placeholders": { "level": {} } + }, + "swipeRightToLeftToReply": "Usap dari kanan ke kiri untuk membalas", + "@swipeRightToLeftToReply": {}, + "searchMore": "Cari lebih banyak...", + "@searchMore": {}, + "gallery": "Galeri", + "@gallery": {}, + "searchIn": "Cari dalam obrolan \"{chat}\"...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "files": "Berkas", + "@files": {}, + "restricted": "Dibatasi", + "@restricted": {}, + "knockRestricted": "Ketukan dibatasi", + "@knockRestricted": {}, + "alwaysUse24HourFormat": "tidak", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." } } diff --git a/assets/l10n/intl_ja.arb b/assets/l10n/intl_ja.arb index a5016852f..70db07f8f 100644 --- a/assets/l10n/intl_ja.arb +++ b/assets/l10n/intl_ja.arb @@ -1,2349 +1,2207 @@ { - "@@locale": "ja", - "@@last_modified": "2021-08-14 12:41:09.978060", - "about": "このアプリについて", - "@about": { - "type": "text", - "placeholders": {} - }, - "accept": "承諾する", - "@accept": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "👍{username}が招待を承諾しました", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "アカウント", - "@account": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "🔐{username}がエンドツーエンド暗号化を有効にしました", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "addEmail": "Eメールを追加", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "admin": "管理者", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "エイリアス", - "@alias": { - "type": "text", - "placeholders": {} - }, - "all": "すべて", - "@all": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "{senderName}は通話に出ました", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "誰でも参加できる", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "appLock": "アプリのロック", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "archive": "アーカイブ", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "ゲストユーザーの参加を許可する", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "これでよろしいですか?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "areYouSureYouWantToLogout": "ログアウトしてよろしいですか?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "他の人を署名するためにはパスフレーズやリカバリーキーを入力してください。", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "{username}の検証リクエストを承認しますか?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "badServerLoginTypesException": "ホームサーバーでサポートされているログインタイプ:\n{serverVersions}\nアプリがサポートしているログインタイプ:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "badServerVersionsException": "ホームサーバーでサポートされているバージョン:\n{serverVersions}\nアプリでは{supportedVersions}しかサポートされていません", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "banFromChat": "チャットからBANする", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "BANされています", - "@banned": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "{username}が{targetName}をBANしました", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "blockDevice": "デバイスをブロックする", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "ブロックしました", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "botMessages": "ボットメッセージ", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "cancel": "キャンセル", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "changeDeviceName": "デバイス名を変更", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "{username}がチャットアバターを変更しました", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatDescriptionTo": "{username}がチャットの説明を「{description}」に変更しました", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheChatNameTo": "{username}がチャットの名前を「{chatname}」に変更しました", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheChatPermissions": "{username}がチャットの権限を変更しました", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "{username}が表示名を「{displayname}」に変更しました", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRules": "{username}がゲストのアクセスルールを変更しました", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRulesTo": "{username}がゲストのアクセスルールを{rules}に変更しました", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheHistoryVisibility": "{username}が履歴の表示設定を変更しました", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "{username}が履歴の表示設定を{rules}に変更しました", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username}が参加ルールを変更しました", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "{username}が参加ルールを{joinRules}に変更しました", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheProfileAvatar": "{username}がアバターを変更しました", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "{username}が部屋のエイリアスを変更しました", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomInvitationLink": "{username}が招待リンクを変更しました", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changePassword": "パスワードを変更", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "changeTheHomeserver": "ホームサーバーの変更", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "スタイルを変更する", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "グループの名前を変更する", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "暗号が破損しています", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chat": "チャット", - "@chat": { - "type": "text", - "placeholders": {} - }, - "chatBackup": "チャットのバックアップ", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "古いメッセージはリカバリーキーで保護されます。紛失しないようにご注意ください。", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "チャットの詳細", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chats": "チャット", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "強いパスワードを選択してください", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "アーカイブを消去", - "@clearArchive": {}, - "close": "閉じる", - "@close": { - "type": "text", - "placeholders": {} - }, - "compareEmojiMatch": "表示されている絵文字が他のデバイスで表示されているものと一致するか確認してください:", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "表示されている数字が他のデバイスで表示されているものと一致するか確認してください:", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "configureChat": "チャットの設定", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "confirm": "確認", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "connect": "接続", - "@connect": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "連絡先に登録された人が招待されました", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "表示名を含んでいます", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "ユーザー名を含んでいます", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "サーバー管理者に通報されました", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "クリップボードにコピーされました", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "copy": "コピー", - "@copy": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "クリップボードにコピー", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "メッセージを解読できませんでした: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "countParticipants": "{count}名の参加者", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "create": "作成", - "@create": { - "type": "text", - "placeholders": {} - }, - "createdTheChat": "💬 {username}がチャットを作成しました", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "currentlyActive": "現在アクティブです", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "ダーク", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "dateWithoutYear": "{month}-{day}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateWithYear": "{year}/{month}/{day}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "deactivateAccountWarning": "あなたのアカウントを無効化します。この操作は元に戻せません!よろしいですか?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "デフォルトの権限レベル", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "delete": "削除", - "@delete": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "アカウントの削除", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "メッセージの削除", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "device": "デバイス", - "@device": { - "type": "text", - "placeholders": {} - }, - "deviceId": "デバイスID", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "デバイス", - "@devices": { - "type": "text", - "placeholders": {} - }, - "directChats": "ダイレクトチャット", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "表示名が変更されました", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "ファイルのダウンロード", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "edit": "編集", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "ブロックしたサーバーを編集", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "表示名を編集", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "ルームエイリアスを編集", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "部屋のアバターを編集する", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Emoteはすでに存在します!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "不正なEmoteショートコード!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "部屋のEmoteパック", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Emote設定", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "emoteShortcode": "Emoteショートコード", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Emoteショートコードと画像を選択してください!", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "空のチャット", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "emoteをグローバルに有効にする", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "暗号化を有効にする", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "enableEncryptionWarning": "一度暗号化を有効にするともとに戻せません。よろしいですか?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "encrypted": "暗号化", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "encryption": "暗号化", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "encryptionNotEnabled": "暗号化されていません", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "{senderName}は通話を切断しました", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "enterAnEmailAddress": "メールアドレスを入力してください", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "enterYourHomeserver": "ホームサーバーを入力してください", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "everythingReady": "すべての準備は完了しました!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "とても攻撃的", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "fileName": "ファイル名", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "fontSize": "フォントサイズ", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "forward": "進む", - "@forward": { - "type": "text", - "placeholders": {} - }, - "fromJoining": "参加時点から閲覧可能", - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "fromTheInvitation": "招待時点から閲覧可能", - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "goToTheNewRoom": "新規ルームへ", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "group": "グループ", - "@group": { - "type": "text", - "placeholders": {} - }, - "groupIsPublic": "グループは公開されています", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "groups": "グループ", - "@groups": { - "type": "text", - "placeholders": {} - }, - "groupWith": "{displayname}とグループを作成する", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "guestsAreForbidden": "ゲストは許可されていません", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "ゲストが許可されています", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "hasWithdrawnTheInvitationFor": "{targetName}の招待を{username}が取り下げました", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "help": "ヘルプ", - "@help": { - "type": "text", - "placeholders": {} - }, - "hideRedactedEvents": "編集済みイベントを非表示にする", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "不明なイベントを非表示にする", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "howOffensiveIsThisContent": "どのくらい攻撃的でしたか?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "id": "ID", - "@id": { - "type": "text", - "placeholders": {} - }, - "identity": "アイデンティティ", - "@identity": { - "type": "text", - "placeholders": {} - }, - "ignore": "無視する", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "無視されたユーザー", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "リンクをクリックしました", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "incorrectPassphraseOrKey": "パスフレーズかリカバリーキーが間違っています", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "非攻撃的", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "連絡先から招待する", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "連絡先から{groupName}に招待する", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "invited": "招待されました", - "@invited": { - "type": "text", - "placeholders": {} - }, - "invitedUser": "📩 {username} が {targetName} を招待しました", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "invitedUsersOnly": "招待されたユーザーのみ", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "inviteForMe": "自分への招待", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "inviteText": "{username}がFluffyChatにあなたを招待しました. \n1. FluffyChatをインストールしてください: https://fluffychat.im \n2. 新しくアカウントを作成するかサインインしてください\n3. 招待リンクを開いてください: {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "isTyping": "が入力しています…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "joinedTheChat": "👋 {username} がチャットに参加しました", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "joinRoom": "部屋に参加", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "kicked": "👞 {username} は {targetName} をキックしました", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickedAndBanned": "🙅 {username} が {targetName} をキックしブロックしました", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickFromChat": "チャットからキックする", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "lastActiveAgo": "最終アクティブ: {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "leave": "退室する", - "@leave": { - "type": "text", - "placeholders": {} - }, - "leftTheChat": "退室しました", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "license": "ライセンス", - "@license": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "ライト", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "loadCountMoreParticipants": "あと{count}名参加者を読み込む", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "loadingPleaseWait": "読み込み中…お待ちください。", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "loadMore": "更に読み込む…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "login": "ログイン", - "@login": { - "type": "text", - "placeholders": {} - }, - "logInTo": "{homeserver}にログインする", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "logout": "ログアウト", - "@logout": { - "type": "text", - "placeholders": {} - }, - "memberChanges": "メンバーの変更", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "mention": "メンション", - "@mention": { - "type": "text", - "placeholders": {} - }, - "messages": "メッセージ", - "@messages": { - "type": "text", - "placeholders": {} - }, - "moderator": "モデレータ", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "muteChat": "チャットのミュート", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "現時点では、エンドツーエンドの暗号化を使用するにはPantalaimonが必要であることに注意してください。", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "newChat": "新規チャット", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "💬 FluffyChatに新しいメッセージがあります", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "newVerificationRequest": "認証リクエスト!", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "next": "次へ", - "@next": { - "type": "text", - "placeholders": {} - }, - "no": "いいえ", - "@no": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "サーバーに接続できません", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "noEmotesFound": "Emoteは見つかりませんでした😕", - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "ルームを非公開にした後暗号化を有効にできます。", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "noGoogleServicesWarning": "あなたのスマホにはGoogleサービスがないようですね。プライバシーを保護するための良い選択です!プッシュ通知を受け取るには https://microg.org/ または https://unifiedpush.org/ を使うことをお勧めします。", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "none": "なし", - "@none": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "パスワードを回復する方法をまだ追加していません。", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "noPermission": "権限がありません", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "部屋は見つかりませんでした…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "notifications": "通知", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "notificationsEnabledForThisAccount": "このアカウントでは通知が有効です", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "numUsersTyping": "{count}人が入力中…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "offensive": "攻撃的", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "offline": "オフライン", - "@offline": { - "type": "text", - "placeholders": {} - }, - "ok": "OK", - "@ok": { - "type": "text", - "placeholders": {} - }, - "online": "オンライン", - "@online": { - "type": "text", - "placeholders": {} - }, - "onlineKeyBackupEnabled": "オンライン鍵バックアップは使用されています", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "おっと、何かがうまくいきませんでした…", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "アプリを開いてメッセージを確認してください", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "openCamera": "カメラを開く", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "participant": "参加者", - "@participant": { - "type": "text", - "placeholders": {} - }, - "passphraseOrKey": "パスフレーズかリカバリーキー", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "password": "パスワード", - "@password": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "パスワードを忘れた", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "パスワードが変更されました", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "passwordRecovery": "パスワードリカバリー", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "people": "人々", - "@people": { - "type": "text", - "placeholders": {} - }, - "pickImage": "画像を選択してください", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "pin": "ピン", - "@pin": { - "type": "text", - "placeholders": {} - }, - "play": "{fileName}を再生する", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "pleaseChooseAPasscode": "パスコードを選んでください", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pleaseClickOnLink": "メールのリンクから進めてください。", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "アプリのロック用に4桁の数字を入力してください。空欄の場合は無効になります。", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "パスワードを入力してください", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "PINを入力してください", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "ユーザー名を入力してください", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "pleaseFollowInstructionsOnWeb": "ウェブサイトにあるやり方を見てから次をタップしてください。", - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "privacy": "プライバシー", - "@privacy": { - "type": "text", - "placeholders": {} - }, - "publicRooms": "公開された部屋", - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "pushRules": "ルールを追加する", - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "reason": "理由", - "@reason": { - "type": "text", - "placeholders": {} - }, - "recording": "録音中", - "@recording": { - "type": "text", - "placeholders": {} - }, - "redactedAnEvent": "{username}がイベントを編集しました", - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "redactMessage": "メッセージを書く", - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "reject": "拒否", - "@reject": { - "type": "text", - "placeholders": {} - }, - "rejectedTheInvitation": "{username}は招待を拒否しました", - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "rejoin": "再参加", - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "remove": "消去", - "@remove": { - "type": "text", - "placeholders": {} - }, - "removeAllOtherDevices": "他のデバイスをすべて削除", - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "removedBy": "{username}によって削除されました", - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removeDevice": "デバイスの削除", - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "unbanFromChat": "チャットからのブロックを解除する", - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "renderRichContent": "リッチメッセージをレンダリングする", - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "replaceRoomWithNewerVersion": "部屋を新しいバージョンに変更する", - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "reply": "返信", - "@reply": { - "type": "text", - "placeholders": {} - }, - "reportMessage": "メッセージを通報", - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "requestPermission": "権限を要求する", - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "roomHasBeenUpgraded": "部屋はアップグレードされました", - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "roomVersion": "ルームバージョン", - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "search": "検索", - "@search": { - "type": "text", - "placeholders": {} - }, - "security": "セキュリティ", - "@security": { - "type": "text", - "placeholders": {} - }, - "seenByUser": "{username}が既読", - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "send": "送信", - "@send": { - "type": "text", - "placeholders": {} - }, - "sendAMessage": "メッセージを送信", - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "sendAudio": "音声の送信", - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "sendFile": "ファイルを送信", - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "sendImage": "画像の送信", - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "sendMessages": "メッセージを送る", - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "sendOriginal": "オリジナルの送信", - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "sendVideo": "動画を送信", - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "sentAFile": "📁 {username}はファイルを送信しました", - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAnAudio": "🎤 {username}は音声を送信しました", - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAPicture": "🖼️ {username}は画像を送信しました", - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentASticker": "😊 {username}はステッカーを送信しました", - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAVideo": "🎥 {username}は動画を送信しました", - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentCallInformations": "{senderName}は通話情報を送信しました", - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "setAsCanonicalAlias": "メインエイリアスに設定", - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "setCustomEmotes": "カスタムエモートの設定", - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "setInvitationLink": "招待リンクを設定する", - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "setPermissionsLevel": "権限レベルをセット", - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "setStatus": "ステータスの設定", - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "settings": "設定", - "@settings": { - "type": "text", - "placeholders": {} - }, - "share": "共有", - "@share": { - "type": "text", - "placeholders": {} - }, - "sharedTheLocation": "{username}は現在地を共有しました", - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "showPassword": "パスワードを表示", - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "skip": "スキップ", - "@skip": { - "type": "text", - "placeholders": {} - }, - "sourceCode": "ソースコード", - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "startedACall": "{senderName}は通話を開始しました", - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "status": "ステータス", - "@status": { - "type": "text", - "placeholders": {} - }, - "statusExampleMessage": "お元気ですか?", - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "submit": "送信", - "@submit": { - "type": "text", - "placeholders": {} - }, - "systemTheme": "システム", - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "theyDontMatch": "違います", - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "theyMatch": "一致しています", - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "title": "FluffyChat", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "toggleFavorite": "お気に入り切り替え", - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "toggleMuted": "ミュート切り替え", - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "toggleUnread": "既読/未読にマーク", - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "tooManyRequestsWarning": "リクエストが多すぎます。また後で試してみてください!", - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "transferFromAnotherDevice": "違うデバイスから移行する", - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "tryToSendAgain": "送信し直してみる", - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "unavailable": "不在", - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "unbannedUser": "{username}が{targetName}のBANを解除しました", - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "unblockDevice": "デバイスをブロック解除する", - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "unknownDevice": "未知デバイス", - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "unknownEncryptionAlgorithm": "未知の暗号化アルゴリズム", - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "unknownEvent": "未知のイベント'{type}'", - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "unmuteChat": "チャットをミュート解除する", - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "unpin": "ピンを外す", - "@unpin": { - "type": "text", - "placeholders": {} - }, - "unreadChats": "{unreadCount, plural, =1{1件の未読メッセージ} other{{unreadCount}件の未読メッセージ}}", - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "userAndOthersAreTyping": "{username}と他{count}名が入力しています…", - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "userAndUserAreTyping": "{username}と{username2}が入力しています…", - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "userIsTyping": "{username}が入力しています…", - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "userLeftTheChat": "🚪 {username}はチャットから退室しました", - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "username": "ユーザー名", - "@username": { - "type": "text", - "placeholders": {} - }, - "userSentUnknownEvent": "{username}は{type}イベントを送信しました", - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "verified": "検証済み", - "@verified": { - "type": "text", - "placeholders": {} - }, - "verify": "確認", - "@verify": { - "type": "text", - "placeholders": {} - }, - "verifyStart": "確認を始める", - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "verifySuccess": "確認が完了しました!", - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "verifyTitle": "他のアカウントを確認中", - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "videoCall": "音声通話", - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "visibilityOfTheChatHistory": "チャット履歴の表示", - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "visibleForAllParticipants": "すべての参加者が閲覧可能", - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "visibleForEveryone": "すべての人が閲覧可能", - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "voiceMessage": "ボイスメッセージ", - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerAcceptRequest": "パートナーのリクエスト承諾待ちです...", - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerEmoji": "パートナーの絵文字承諾待ちです...", - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerNumbers": "パートナーの数字承諾待ちです…", - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "wallpaper": "壁紙", - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "warning": "警告!", - "@warning": { - "type": "text", - "placeholders": {} - }, - "weSentYouAnEmail": "あなたにメールを送信しました", - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "whoCanPerformWhichAction": "誰がどの操作を実行できるか", - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "whoIsAllowedToJoinThisGroup": "誰がこのチャットに入れますか", - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "whyDoYouWantToReportThis": "これを通報する理由", - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "wipeChatBackup": "チャットのバックアップを消去して、新しいリカバリーキーを作りますか?", - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "withTheseAddressesRecoveryDescription": "これらのアドレスを使用すると、パスワードを回復することができます。", - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "writeAMessage": "メッセージを入力してください…", - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "yes": "はい", - "@yes": { - "type": "text", - "placeholders": {} - }, - "you": "あなた", - "@you": { - "type": "text", - "placeholders": {} - }, - "youAreNoLongerParticipatingInThisChat": "あなたはもうこのチャットの参加者ではありません", - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "youHaveBeenBannedFromThisChat": "チャットからBANされてしまいました", - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "yourPublicKey": "あなたの公開鍵", - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "allChats": "すべて会話", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "addToSpace": "スペースに追加", - "@addToSpace": {}, - "cantOpenUri": "URIが開けません {uri}", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "repeatPassword": "パスワードを繰り返そ", - "@repeatPassword": {}, - "autoplayImages": "GIFを自動的に再生する", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "yourChatBackupHasBeenSetUp": "チャットバックアップを設定ました。", - "@yourChatBackupHasBeenSetUp": {}, - "sendOnEnter": "Enterで送信", - "@sendOnEnter": {}, - "changeYourAvatar": "アバタるを変化しする", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "このスペースにチャットが追加されました", - "@chatHasBeenAddedToThisSpace": {}, - "commandHint_ban": "このユーザーを禁止する", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_clearcache": "キャッシュをクリアする", - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "commandInvalid": "コマンドが無効", - "@commandInvalid": { - "type": "text" - }, - "commandHint_create": "空のグループチャットを作成\n暗号化を無効にするには、--no-encryption を使用", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "commandHint_discardsession": "セッションを破棄", - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "confirmMatrixId": "アカウントを削除するには、Matrix IDを確認してください。", - "@confirmMatrixId": {}, - "commandHint_markasgroup": "グループとしてマーク", - "@commandHint_markasgroup": {}, - "commandHint_join": "指定した部屋に参加", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_send": "テキストを送信", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "hydrate": "バックアップファイルから復元", - "@hydrate": {}, - "commandHint_html": "HTML形式のテキストを送信", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "指定したユーザーをこの部屋に招待", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandMissing": "{command} はコマンドではありません。", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "oneClientLoggedOut": "クライアントの 1つがログアウトしました", - "@oneClientLoggedOut": {}, - "addAccount": "アカウントを追加", - "@addAccount": {}, - "editBundlesForAccount": "このアカウントのバンドルを編集", - "@editBundlesForAccount": {}, - "unverified": "未検証", - "@unverified": {}, - "sender": "送信者", - "@sender": {}, - "placeCall": "電話をかける", - "@placeCall": {}, - "voiceCall": "音声通話", - "@voiceCall": {}, - "unsupportedAndroidVersionLong": "この機能を利用するには、より新しいAndroidのバージョンが必要です。アップデートまたはLineage OSのサポートをご確認ください。", - "@unsupportedAndroidVersionLong": {}, - "widgetVideo": "動画", - "@widgetVideo": {}, - "widgetName": "名称", - "@widgetName": {}, - "widgetCustom": "カスタム", - "@widgetCustom": {}, - "widgetJitsi": "Jitsi Meet", - "@widgetJitsi": {}, - "dehydrateWarning": "この操作は元に戻せません。バックアップファイルを安全に保存してください。", - "@dehydrateWarning": {}, - "dehydrate": "セッションのエクスポートとデバイスの消去", - "@dehydrate": {}, - "messageType": "メッセージの種類", - "@messageType": {}, - "start": "開始", - "@start": {}, - "publish": "公開", - "@publish": {}, - "indexedDbErrorTitle": "プライベートモードに関する問題", - "@indexedDbErrorTitle": {}, - "addWidget": "ウィジェットを追加", - "@addWidget": {}, - "youBannedUser": "{user} を禁止しました", - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "youJoinedTheChat": "チャットに参加しました", - "@youJoinedTheChat": {}, - "youHaveWithdrawnTheInvitationFor": "{user} への招待を取り下げました", - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "users": "ユーザー", - "@users": {}, - "youRejectedTheInvitation": "招待を拒否しました", - "@youRejectedTheInvitation": {}, - "screenSharingDetail": "FuffyChatで画面を共有しています", - "@screenSharingDetail": {}, - "homeserver": "ホームサーバー", - "@homeserver": {}, - "scanQrCode": "QRコードをスキャン", - "@scanQrCode": {}, - "obtainingLocation": "位置情報を取得しています…", - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "addToBundle": "バンドルに追加", - "@addToBundle": {}, - "removeFromBundle": "このバンドルから削除", - "@removeFromBundle": {}, - "bundleName": "バンドル名", - "@bundleName": {}, - "noMatrixServer": "{server1} はMatrixのサーバーではありません。代わりに {server2} を使用しますか?", - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "openVideoCamera": "ビデオ用にカメラを開く", - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "link": "リンク", - "@link": {}, - "or": "または", - "@or": { - "type": "text", - "placeholders": {} - }, - "register": "登録", - "@register": { - "type": "text", - "placeholders": {} - }, - "removeYourAvatar": "アバターを削除する", - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "saveFile": "ファイルを保存", - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "recoveryKey": "リカバリーキー", - "@recoveryKey": {}, - "singlesignon": "シングルサインオン", - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "spaceIsPublic": "スペースは公開されています", - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "spaceName": "スペース名", - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "startFirstChat": "最初のチャットを開始する", - "@startFirstChat": {}, - "addToSpaceDescription": "このチャットを追加するスペースを選択してください。", - "@addToSpaceDescription": {}, - "messageInfo": "メッセージの情報", - "@messageInfo": {}, - "openGallery": "ギャラリーを開く", - "@openGallery": {}, - "removeFromSpace": "スペースから削除", - "@removeFromSpace": {}, - "pleaseEnterRecoveryKeyDescription": "古いメッセージを解除するには、以前のセッションで生成されたリカバリーキーを入力してください。リカバリーキーはパスワードではありません。", - "@pleaseEnterRecoveryKeyDescription": {}, - "videoWithSize": "ビデオ ({size})", - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "openChat": "チャットを開く", - "@openChat": {}, - "experimentalVideoCalls": "実験的なビデオ通話", - "@experimentalVideoCalls": {}, - "emailOrUsername": "メールアドレスまたはユーザー名", - "@emailOrUsername": {}, - "switchToAccount": "アカウント {number} に切り替える", - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "nextAccount": "次のアカウント", - "@nextAccount": {}, - "youAcceptedTheInvitation": "👍 招待を承諾しました", - "@youAcceptedTheInvitation": {}, - "errorAddingWidget": "ウィジェットの追加中にエラーが発生しました。", - "@errorAddingWidget": {}, - "widgetNameError": "表示名を入力してください。", - "@widgetNameError": {}, - "youUnbannedUser": "{user} の禁止を解除しました", - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "youInvitedBy": "📩 {user} から招待されました", - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "youKicked": "👞 {user} をキックしました", - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "youKickedAndBanned": "🙅 {user} をキックしてブロックしました", - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "storeInAppleKeyChain": "Apple KeyChainに保存", - "@storeInAppleKeyChain": {}, - "storeInAndroidKeystore": "Android KeyStoreに保存する", - "@storeInAndroidKeystore": {}, - "storeInSecureStorageDescription": "このデバイスの安全なストレージにリカバリーキーを保存。", - "@storeInSecureStorageDescription": {}, - "unlockOldMessages": "古いメッセージのロックを解除する", - "@unlockOldMessages": {}, - "callingAccount": "通話アカウント", - "@callingAccount": {}, - "callingPermissions": "通話の権限", - "@callingPermissions": {}, - "screenSharingTitle": "画面共有", - "@screenSharingTitle": {}, - "foregroundServiceRunning": "この通知は、フォアグラウンド サービスの実行中に表示されます。", - "@foregroundServiceRunning": {}, - "custom": "カスタム", - "@custom": {}, - "countFiles": "{count}個のファイル", - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "storeSecurlyOnThisDevice": "このデバイスに安全に保管する", - "@storeSecurlyOnThisDevice": {}, - "whyIsThisMessageEncrypted": "このメッセージが読めない理由", - "@whyIsThisMessageEncrypted": {}, - "otherCallingPermissions": "マイク、カメラ、その他FluffyChatの権限", - "@otherCallingPermissions": {}, - "appearOnTopDetails": "アプリをトップに表示できるようにする(すでに通話アカウントとしてFluffychatを設定している場合は必要ありません)", - "@appearOnTopDetails": {}, - "dehydrateTorLong": "TOR ユーザーの場合、ウィンドウを閉じる前にセッションをエクスポートすることをお勧めします。", - "@dehydrateTorLong": {}, - "hydrateTorLong": "前回、TOR でセッションをエクスポートしましたか?すぐにインポートしてチャットを続けましょう。", - "@hydrateTorLong": {}, - "enableMultiAccounts": "(ベータ版) このデバイスで複数のアカウントを有効にする", - "@enableMultiAccounts": {}, - "pleaseEnterRecoveryKey": "リカバリーキーを入力してください。", - "@pleaseEnterRecoveryKey": {}, - "serverRequiresEmail": "このサーバーは、登録のためにメールアドレスを検証する必要があります。", - "@serverRequiresEmail": {}, - "sendSticker": "ステッカーを送る", - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "synchronizingPleaseWait": "同期中...お待ちください。", - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "emojis": "絵文字", - "@emojis": {}, - "markAsRead": "既読にする", - "@markAsRead": {}, - "videoCallsBetaWarning": "ビデオ通話は、現在ベータ版であることにご注意ください。すべてのプラットフォームで期待通りに動作しない、あるいはまったく動作しない可能性があります。", - "@videoCallsBetaWarning": {}, - "confirmEventUnpin": "イベントの固定を完全に解除してもよろしいですか?", - "@confirmEventUnpin": {}, - "unsupportedAndroidVersion": "サポートされていないAndroidのバージョン", - "@unsupportedAndroidVersion": {}, - "user": "ユーザー", - "@user": {}, - "newGroup": "新しいグループ", - "@newGroup": {}, - "noBackupWarning": "警告!チャットのバックアップを有効にしないと、暗号化されたメッセージにアクセスできなくなります。ログアウトする前に、まずチャットのバックアップを有効にすることを強くお勧めします。", - "@noBackupWarning": {}, - "disableEncryptionWarning": "セキュリティ上の理由から、以前は暗号化が有効だったチャットで暗号化を無効にすることはできません。", - "@disableEncryptionWarning": {}, - "youInvitedUser": "📩 {user} を招待しました", - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "reactedWith": "{sender} が {reaction} で反応しました", - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "createNewSpace": "新しいスペース", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "widgetUrlError": "有効なURLではありません。", - "@widgetUrlError": {}, - "reportUser": "ユーザーを報告", - "@reportUser": {}, - "errorObtainingLocation": "位置情報の取得中にエラーが発生しました: {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "pinMessage": "部屋にピン留めする", - "@pinMessage": {}, - "previousAccount": "前のアカウント", - "@previousAccount": {}, - "pleaseChoose": "選択してください", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "oopsPushError": "おっと!残念ながら、プッシュ通知の設定中にエラーが発生しました。", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "noOtherDevicesFound": "他のデバイスが見つかりません", - "@noOtherDevicesFound": {}, - "recoveryKeyLost": "リカバリーキーを紛失した場合", - "@recoveryKeyLost": {}, - "shareLocation": "位置情報の共有", - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "time": "時間", - "@time": {}, - "sendAsText": "テキストとして送信", - "@sendAsText": { - "type": "text" - }, - "commandHint_googly": "ぎょろ目を送る", - "@commandHint_googly": {}, - "commandHint_hug": "ハグを送る", - "@commandHint_hug": {}, - "encryptThisChat": "このチャットを暗号化する", - "@encryptThisChat": {}, - "commandHint_markasdm": "ダイレクトメッセージの部屋としてマークする", - "@commandHint_markasdm": {}, - "commandHint_dm": "ダイレクトチャットを開始する\n暗号化を無効にするには、--no-encryptionを使用してください", - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "commandHint_leave": "この部屋を退出", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_myroomavatar": "この部屋の写真を設定する (mxc-uriで)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_myroomnick": "この部屋の表示名を設定する", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_plain": "書式設定されていないテキストを送信する", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_react": "リアクションとして返信を送信する", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "dehydrateTor": "TOR ユーザー: セッションをエクスポート", - "@dehydrateTor": {}, - "hydrateTor": "TOR ユーザー: セッションのエクスポートをインポート", - "@hydrateTor": {}, - "locationDisabledNotice": "位置情報サービスが無効になっています。位置情報を共有できるようにするには、位置情報サービスを有効にしてください。", - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "locationPermissionDeniedNotice": "位置情報の権限が拒否されました。位置情報を共有できるように許可してください。", - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "deviceKeys": "デバイスキー:", - "@deviceKeys": {}, - "sorryThatsNotPossible": "申し訳ありません...それは不可能です", - "@sorryThatsNotPossible": {}, - "wasDirectChatDisplayName": "空のチャット (以前は {oldDisplayName})", - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "doNotShowAgain": "今後表示しない", - "@doNotShowAgain": {}, - "hideUnimportantStateEvents": "重要でない状態イベントを非表示にする", - "@hideUnimportantStateEvents": {}, - "numChats": "{number} チャット", - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "allSpaces": "すべてのスペース", - "@allSpaces": {}, - "enterRoom": "部屋に入る", - "@enterRoom": {}, - "enterSpace": "スペースに入る", - "@enterSpace": {}, - "newSpace": "新しいスペース", - "@newSpace": {}, - "reopenChat": "チャットを再開する", - "@reopenChat": {}, - "signInWith": "{provider}でログイン", - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "signInWithPassword": "パスワードでログイン", - "@signInWithPassword": {}, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@dismiss": {}, - "@reportErrorDescription": {}, - "@indexedDbErrorLong": {}, - "@setColorTheme": {}, - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "@banUserDescription": {}, - "@widgetEtherpad": {}, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@unbanUserDescription": {}, - "@messagesStyle": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@noKeyForThisMessage": {}, - "@pushNotificationsNotAvailable": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@makeAdminDescription": {}, - "@saveKeyManuallyDescription": {}, - "@setChatDescription": {}, - "@importFromZipFile": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@fileIsTooBigForServer": {}, - "@readUpToHere": {}, - "@optionalRedactReason": {}, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@redactMessageDescription": {}, - "@invalidInput": {}, - "@report": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@addChatDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@openLinkInBrowser": {}, - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "@importEmojis": {}, - "@noChatDescriptionYet": {}, - "@learnMore": {}, - "@notAnImage": {}, - "@chatDescriptionHasBeenChanged": {}, - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "@roomUpgradeDescription": {}, - "@pleaseEnterANumber": {}, - "@profileNotFound": {}, - "@jump": {}, - "@shareInviteLink": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@replace": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@invite": {} -} \ No newline at end of file + "@@locale": "ja", + "@@last_modified": "2021-08-14 12:41:09.978060", + "about": "このアプリについて", + "@about": { + "type": "text", + "placeholders": {} + }, + "accept": "承諾する", + "@accept": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "👍{username}が招待を承諾しました", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "account": "アカウント", + "@account": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "🔐{username}がエンドツーエンド暗号化を有効にしました", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "addEmail": "Eメールを追加", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "admin": "管理者", + "@admin": { + "type": "text", + "placeholders": {} + }, + "alias": "エイリアス", + "@alias": { + "type": "text", + "placeholders": {} + }, + "all": "すべて", + "@all": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "{senderName}は通話に出ました", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "anyoneCanJoin": "誰でも参加できる", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "appLock": "アプリのロック", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "archive": "アーカイブ", + "@archive": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "ゲストユーザーの参加を許可する", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "これでよろしいですか?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "areYouSureYouWantToLogout": "ログアウトしてよろしいですか?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "askSSSSSign": "他の人を署名するためにはパスフレーズやリカバリーキーを入力してください。", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "{username}の検証リクエストを承認しますか?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "badServerLoginTypesException": "ホームサーバーでサポートされているログインタイプ:\n{serverVersions}\nアプリがサポートしているログインタイプ:\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "badServerVersionsException": "ホームサーバーでサポートされているバージョン:\n{serverVersions}\nアプリでは{supportedVersions}しかサポートされていません", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "banFromChat": "チャットからBANする", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "banned": "BANされています", + "@banned": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "{username}が{targetName}をBANしました", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "blockDevice": "デバイスをブロックする", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "blocked": "ブロックしました", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "botMessages": "ボットメッセージ", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "cancel": "キャンセル", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "changeDeviceName": "デバイス名を変更", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "changedTheChatAvatar": "{username}がチャットアバターを変更しました", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatDescriptionTo": "{username}がチャットの説明を「{description}」に変更しました", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "changedTheChatNameTo": "{username}がチャットの名前を「{chatname}」に変更しました", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changedTheChatPermissions": "{username}がチャットの権限を変更しました", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "{username}が表示名を「{displayname}」に変更しました", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRules": "{username}がゲストのアクセスルールを変更しました", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheGuestAccessRulesTo": "{username}がゲストのアクセスルールを{rules}に変更しました", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheHistoryVisibility": "{username}が履歴の表示設定を変更しました", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibilityTo": "{username}が履歴の表示設定を{rules}に変更しました", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRules": "{username}が参加ルールを変更しました", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheJoinRulesTo": "{username}が参加ルールを{joinRules}に変更しました", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheProfileAvatar": "{username}がアバターを変更しました", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "{username}が部屋のエイリアスを変更しました", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomInvitationLink": "{username}が招待リンクを変更しました", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changePassword": "パスワードを変更", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "changeTheHomeserver": "ホームサーバーの変更", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "スタイルを変更する", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "グループの名前を変更する", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "channelCorruptedDecryptError": "暗号が破損しています", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "chat": "チャット", + "@chat": { + "type": "text", + "placeholders": {} + }, + "chatBackup": "チャットのバックアップ", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "chatBackupDescription": "古いメッセージはリカバリーキーで保護されます。紛失しないようにご注意ください。", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "chatDetails": "チャットの詳細", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chats": "チャット", + "@chats": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "強いパスワードを選択してください", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "clearArchive": "アーカイブを消去", + "@clearArchive": {}, + "close": "閉じる", + "@close": { + "type": "text", + "placeholders": {} + }, + "compareEmojiMatch": "表示されている絵文字が他のデバイスで表示されているものと一致するか確認してください:", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "表示されている数字が他のデバイスで表示されているものと一致するか確認してください:", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "configureChat": "チャットの設定", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "confirm": "確認", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "connect": "接続", + "@connect": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "連絡先に登録された人が招待されました", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "表示名を含んでいます", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "containsUserName": "ユーザー名を含んでいます", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "サーバー管理者に通報されました", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "クリップボードにコピーされました", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "copy": "コピー", + "@copy": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "クリップボードにコピー", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "メッセージを解読できませんでした: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "countParticipants": "{count}名の参加者", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "create": "作成", + "@create": { + "type": "text", + "placeholders": {} + }, + "createdTheChat": "💬 {username}がチャットを作成しました", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "currentlyActive": "現在アクティブです", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "ダーク", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "dateWithoutYear": "{month}-{day}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "dateWithYear": "{year}/{month}/{day}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "deactivateAccountWarning": "あなたのアカウントを無効化します。この操作は元に戻せません!よろしいですか?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "デフォルトの権限レベル", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "delete": "削除", + "@delete": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "アカウントの削除", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "メッセージの削除", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "device": "デバイス", + "@device": { + "type": "text", + "placeholders": {} + }, + "deviceId": "デバイスID", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "devices": "デバイス", + "@devices": { + "type": "text", + "placeholders": {} + }, + "directChats": "ダイレクトチャット", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "displaynameHasBeenChanged": "表示名が変更されました", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "ファイルのダウンロード", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "edit": "編集", + "@edit": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "ブロックしたサーバーを編集", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "表示名を編集", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "ルームエイリアスを編集", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "部屋のアバターを編集する", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "Emoteはすでに存在します!", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "emoteInvalid": "不正なEmoteショートコード!", + "@emoteInvalid": { + "type": "text", + "placeholders": {} + }, + "emotePacks": "部屋のEmoteパック", + "@emotePacks": { + "type": "text", + "placeholders": {} + }, + "emoteSettings": "Emote設定", + "@emoteSettings": { + "type": "text", + "placeholders": {} + }, + "emoteShortcode": "Emoteショートコード", + "@emoteShortcode": { + "type": "text", + "placeholders": {} + }, + "emoteWarnNeedToPick": "Emoteショートコードと画像を選択してください!", + "@emoteWarnNeedToPick": { + "type": "text", + "placeholders": {} + }, + "emptyChat": "空のチャット", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "enableEmotesGlobally": "emoteをグローバルに有効にする", + "@enableEmotesGlobally": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "暗号化を有効にする", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "enableEncryptionWarning": "一度暗号化を有効にするともとに戻せません。よろしいですか?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "encrypted": "暗号化", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "encryption": "暗号化", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "encryptionNotEnabled": "暗号化されていません", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "{senderName}は通話を切断しました", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "enterAnEmailAddress": "メールアドレスを入力してください", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "enterYourHomeserver": "ホームサーバーを入力してください", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "everythingReady": "すべての準備は完了しました!", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "extremeOffensive": "とても攻撃的", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "fileName": "ファイル名", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "fontSize": "フォントサイズ", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "forward": "進む", + "@forward": { + "type": "text", + "placeholders": {} + }, + "fromJoining": "参加時点から閲覧可能", + "@fromJoining": { + "type": "text", + "placeholders": {} + }, + "fromTheInvitation": "招待時点から閲覧可能", + "@fromTheInvitation": { + "type": "text", + "placeholders": {} + }, + "goToTheNewRoom": "新規ルームへ", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "group": "グループ", + "@group": { + "type": "text", + "placeholders": {} + }, + "groupIsPublic": "グループは公開されています", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "groups": "グループ", + "@groups": { + "type": "text", + "placeholders": {} + }, + "groupWith": "{displayname}とグループを作成する", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "guestsAreForbidden": "ゲストは許可されていません", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "ゲストが許可されています", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "hasWithdrawnTheInvitationFor": "{targetName}の招待を{username}が取り下げました", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "help": "ヘルプ", + "@help": { + "type": "text", + "placeholders": {} + }, + "hideRedactedEvents": "編集済みイベントを非表示にする", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "不明なイベントを非表示にする", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "howOffensiveIsThisContent": "どのくらい攻撃的でしたか?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "id": "ID", + "@id": { + "type": "text", + "placeholders": {} + }, + "identity": "アイデンティティ", + "@identity": { + "type": "text", + "placeholders": {} + }, + "ignore": "無視する", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "無視されたユーザー", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "リンクをクリックしました", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "incorrectPassphraseOrKey": "パスフレーズかリカバリーキーが間違っています", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "非攻撃的", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "連絡先から招待する", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "連絡先から{groupName}に招待する", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "invited": "招待されました", + "@invited": { + "type": "text", + "placeholders": {} + }, + "invitedUser": "📩 {username} が {targetName} を招待しました", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "invitedUsersOnly": "招待されたユーザーのみ", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "inviteForMe": "自分への招待", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "inviteText": "{username}がFluffyChatにあなたを招待しました. \n1. FluffyChatをインストールしてください: https://fluffychat.im \n2. 新しくアカウントを作成するかサインインしてください\n3. 招待リンクを開いてください: {link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "isTyping": "が入力しています…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "joinedTheChat": "👋 {username} がチャットに参加しました", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "joinRoom": "部屋に参加", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "kicked": "👞 {username} は {targetName} をキックしました", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickedAndBanned": "🙅 {username} が {targetName} をキックしブロックしました", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickFromChat": "チャットからキックする", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "lastActiveAgo": "最終アクティブ: {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "leave": "退室する", + "@leave": { + "type": "text", + "placeholders": {} + }, + "leftTheChat": "退室しました", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "license": "ライセンス", + "@license": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "ライト", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "loadCountMoreParticipants": "あと{count}名参加者を読み込む", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "loadingPleaseWait": "読み込み中…お待ちください。", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "loadMore": "更に読み込む…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "login": "ログイン", + "@login": { + "type": "text", + "placeholders": {} + }, + "logInTo": "{homeserver}にログインする", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "logout": "ログアウト", + "@logout": { + "type": "text", + "placeholders": {} + }, + "memberChanges": "メンバーの変更", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "mention": "メンション", + "@mention": { + "type": "text", + "placeholders": {} + }, + "messages": "メッセージ", + "@messages": { + "type": "text", + "placeholders": {} + }, + "moderator": "モデレータ", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "muteChat": "チャットのミュート", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "現時点では、エンドツーエンドの暗号化を使用するにはPantalaimonが必要であることに注意してください。", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "newChat": "新規チャット", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "💬 FluffyChatに新しいメッセージがあります", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "newVerificationRequest": "認証リクエスト!", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "next": "次へ", + "@next": { + "type": "text", + "placeholders": {} + }, + "no": "いいえ", + "@no": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "サーバーに接続できません", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "noEmotesFound": "Emoteは見つかりませんでした😕", + "@noEmotesFound": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "ルームを非公開にした後暗号化を有効にできます。", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "noGoogleServicesWarning": "あなたのスマホにはGoogleサービスがないようですね。プライバシーを保護するための良い選択です!プッシュ通知を受け取るには https://microg.org/ または https://unifiedpush.org/ を使うことをお勧めします。", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "none": "なし", + "@none": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "パスワードを回復する方法をまだ追加していません。", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "noPermission": "権限がありません", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "部屋は見つかりませんでした…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "notifications": "通知", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "notificationsEnabledForThisAccount": "このアカウントでは通知が有効です", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "numUsersTyping": "{count}人が入力中…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "offensive": "攻撃的", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "offline": "オフライン", + "@offline": { + "type": "text", + "placeholders": {} + }, + "ok": "OK", + "@ok": { + "type": "text", + "placeholders": {} + }, + "online": "オンライン", + "@online": { + "type": "text", + "placeholders": {} + }, + "onlineKeyBackupEnabled": "オンライン鍵バックアップは使用されています", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "おっと、何かがうまくいきませんでした…", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "アプリを開いてメッセージを確認してください", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "openCamera": "カメラを開く", + "@openCamera": { + "type": "text", + "placeholders": {} + }, + "participant": "参加者", + "@participant": { + "type": "text", + "placeholders": {} + }, + "passphraseOrKey": "パスフレーズかリカバリーキー", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "password": "パスワード", + "@password": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "パスワードを忘れた", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "パスワードが変更されました", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "passwordRecovery": "パスワードリカバリー", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "people": "人々", + "@people": { + "type": "text", + "placeholders": {} + }, + "pickImage": "画像を選択してください", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "pin": "ピン", + "@pin": { + "type": "text", + "placeholders": {} + }, + "play": "{fileName}を再生する", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "pleaseChooseAPasscode": "パスコードを選んでください", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pleaseClickOnLink": "メールのリンクから進めてください。", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "アプリのロック用に4桁の数字を入力してください。空欄の場合は無効になります。", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "パスワードを入力してください", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "PINを入力してください", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "ユーザー名を入力してください", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "pleaseFollowInstructionsOnWeb": "ウェブサイトにあるやり方を見てから次をタップしてください。", + "@pleaseFollowInstructionsOnWeb": { + "type": "text", + "placeholders": {} + }, + "privacy": "プライバシー", + "@privacy": { + "type": "text", + "placeholders": {} + }, + "publicRooms": "公開された部屋", + "@publicRooms": { + "type": "text", + "placeholders": {} + }, + "pushRules": "ルールを追加する", + "@pushRules": { + "type": "text", + "placeholders": {} + }, + "reason": "理由", + "@reason": { + "type": "text", + "placeholders": {} + }, + "recording": "録音中", + "@recording": { + "type": "text", + "placeholders": {} + }, + "redactedAnEvent": "{username}がイベントを編集しました", + "@redactedAnEvent": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "redactMessage": "メッセージを書く", + "@redactMessage": { + "type": "text", + "placeholders": {} + }, + "reject": "拒否", + "@reject": { + "type": "text", + "placeholders": {} + }, + "rejectedTheInvitation": "{username}は招待を拒否しました", + "@rejectedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "rejoin": "再参加", + "@rejoin": { + "type": "text", + "placeholders": {} + }, + "remove": "消去", + "@remove": { + "type": "text", + "placeholders": {} + }, + "removeAllOtherDevices": "他のデバイスをすべて削除", + "@removeAllOtherDevices": { + "type": "text", + "placeholders": {} + }, + "removedBy": "{username}によって削除されました", + "@removedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removeDevice": "デバイスの削除", + "@removeDevice": { + "type": "text", + "placeholders": {} + }, + "unbanFromChat": "チャットからのブロックを解除する", + "@unbanFromChat": { + "type": "text", + "placeholders": {} + }, + "renderRichContent": "リッチメッセージをレンダリングする", + "@renderRichContent": { + "type": "text", + "placeholders": {} + }, + "replaceRoomWithNewerVersion": "部屋を新しいバージョンに変更する", + "@replaceRoomWithNewerVersion": { + "type": "text", + "placeholders": {} + }, + "reply": "返信", + "@reply": { + "type": "text", + "placeholders": {} + }, + "reportMessage": "メッセージを通報", + "@reportMessage": { + "type": "text", + "placeholders": {} + }, + "requestPermission": "権限を要求する", + "@requestPermission": { + "type": "text", + "placeholders": {} + }, + "roomHasBeenUpgraded": "部屋はアップグレードされました", + "@roomHasBeenUpgraded": { + "type": "text", + "placeholders": {} + }, + "roomVersion": "ルームバージョン", + "@roomVersion": { + "type": "text", + "placeholders": {} + }, + "search": "検索", + "@search": { + "type": "text", + "placeholders": {} + }, + "security": "セキュリティ", + "@security": { + "type": "text", + "placeholders": {} + }, + "seenByUser": "{username}が既読", + "@seenByUser": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "send": "送信", + "@send": { + "type": "text", + "placeholders": {} + }, + "sendAMessage": "メッセージを送信", + "@sendAMessage": { + "type": "text", + "placeholders": {} + }, + "sendAudio": "音声の送信", + "@sendAudio": { + "type": "text", + "placeholders": {} + }, + "sendFile": "ファイルを送信", + "@sendFile": { + "type": "text", + "placeholders": {} + }, + "sendImage": "画像の送信", + "@sendImage": { + "type": "text", + "placeholders": {} + }, + "sendMessages": "メッセージを送る", + "@sendMessages": { + "type": "text", + "placeholders": {} + }, + "sendOriginal": "オリジナルの送信", + "@sendOriginal": { + "type": "text", + "placeholders": {} + }, + "sendVideo": "動画を送信", + "@sendVideo": { + "type": "text", + "placeholders": {} + }, + "sentAFile": "📁 {username}はファイルを送信しました", + "@sentAFile": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAnAudio": "🎤 {username}は音声を送信しました", + "@sentAnAudio": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAPicture": "🖼️ {username}は画像を送信しました", + "@sentAPicture": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentASticker": "😊 {username}はステッカーを送信しました", + "@sentASticker": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAVideo": "🎥 {username}は動画を送信しました", + "@sentAVideo": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentCallInformations": "{senderName}は通話情報を送信しました", + "@sentCallInformations": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "setAsCanonicalAlias": "メインエイリアスに設定", + "@setAsCanonicalAlias": { + "type": "text", + "placeholders": {} + }, + "setCustomEmotes": "カスタムエモートの設定", + "@setCustomEmotes": { + "type": "text", + "placeholders": {} + }, + "setInvitationLink": "招待リンクを設定する", + "@setInvitationLink": { + "type": "text", + "placeholders": {} + }, + "setPermissionsLevel": "権限レベルをセット", + "@setPermissionsLevel": { + "type": "text", + "placeholders": {} + }, + "setStatus": "ステータスの設定", + "@setStatus": { + "type": "text", + "placeholders": {} + }, + "settings": "設定", + "@settings": { + "type": "text", + "placeholders": {} + }, + "share": "共有", + "@share": { + "type": "text", + "placeholders": {} + }, + "sharedTheLocation": "{username}は現在地を共有しました", + "@sharedTheLocation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "showPassword": "パスワードを表示", + "@showPassword": { + "type": "text", + "placeholders": {} + }, + "skip": "スキップ", + "@skip": { + "type": "text", + "placeholders": {} + }, + "sourceCode": "ソースコード", + "@sourceCode": { + "type": "text", + "placeholders": {} + }, + "startedACall": "{senderName}は通話を開始しました", + "@startedACall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "status": "ステータス", + "@status": { + "type": "text", + "placeholders": {} + }, + "statusExampleMessage": "お元気ですか?", + "@statusExampleMessage": { + "type": "text", + "placeholders": {} + }, + "submit": "送信", + "@submit": { + "type": "text", + "placeholders": {} + }, + "systemTheme": "システム", + "@systemTheme": { + "type": "text", + "placeholders": {} + }, + "theyDontMatch": "違います", + "@theyDontMatch": { + "type": "text", + "placeholders": {} + }, + "theyMatch": "一致しています", + "@theyMatch": { + "type": "text", + "placeholders": {} + }, + "title": "FluffyChat", + "@title": { + "description": "Title for the application", + "type": "text", + "placeholders": {} + }, + "toggleFavorite": "お気に入り切り替え", + "@toggleFavorite": { + "type": "text", + "placeholders": {} + }, + "toggleMuted": "ミュート切り替え", + "@toggleMuted": { + "type": "text", + "placeholders": {} + }, + "toggleUnread": "既読/未読にマーク", + "@toggleUnread": { + "type": "text", + "placeholders": {} + }, + "tooManyRequestsWarning": "リクエストが多すぎます。また後で試してみてください!", + "@tooManyRequestsWarning": { + "type": "text", + "placeholders": {} + }, + "transferFromAnotherDevice": "違うデバイスから移行する", + "@transferFromAnotherDevice": { + "type": "text", + "placeholders": {} + }, + "tryToSendAgain": "送信し直してみる", + "@tryToSendAgain": { + "type": "text", + "placeholders": {} + }, + "unavailable": "不在", + "@unavailable": { + "type": "text", + "placeholders": {} + }, + "unbannedUser": "{username}が{targetName}のBANを解除しました", + "@unbannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "unblockDevice": "デバイスをブロック解除する", + "@unblockDevice": { + "type": "text", + "placeholders": {} + }, + "unknownDevice": "未知デバイス", + "@unknownDevice": { + "type": "text", + "placeholders": {} + }, + "unknownEncryptionAlgorithm": "未知の暗号化アルゴリズム", + "@unknownEncryptionAlgorithm": { + "type": "text", + "placeholders": {} + }, + "unknownEvent": "未知のイベント'{type}'", + "@unknownEvent": { + "type": "text", + "placeholders": { + "type": {} + } + }, + "unmuteChat": "チャットをミュート解除する", + "@unmuteChat": { + "type": "text", + "placeholders": {} + }, + "unpin": "ピンを外す", + "@unpin": { + "type": "text", + "placeholders": {} + }, + "unreadChats": "{unreadCount, plural, =1{1件の未読メッセージ} other{{unreadCount}件の未読メッセージ}}", + "@unreadChats": { + "type": "text", + "placeholders": { + "unreadCount": {} + } + }, + "userAndOthersAreTyping": "{username}と他{count}名が入力しています…", + "@userAndOthersAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "count": {} + } + }, + "userAndUserAreTyping": "{username}と{username2}が入力しています…", + "@userAndUserAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "username2": {} + } + }, + "userIsTyping": "{username}が入力しています…", + "@userIsTyping": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "userLeftTheChat": "🚪 {username}はチャットから退室しました", + "@userLeftTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "username": "ユーザー名", + "@username": { + "type": "text", + "placeholders": {} + }, + "userSentUnknownEvent": "{username}は{type}イベントを送信しました", + "@userSentUnknownEvent": { + "type": "text", + "placeholders": { + "username": {}, + "type": {} + } + }, + "verified": "検証済み", + "@verified": { + "type": "text", + "placeholders": {} + }, + "verify": "確認", + "@verify": { + "type": "text", + "placeholders": {} + }, + "verifyStart": "確認を始める", + "@verifyStart": { + "type": "text", + "placeholders": {} + }, + "verifySuccess": "確認が完了しました!", + "@verifySuccess": { + "type": "text", + "placeholders": {} + }, + "verifyTitle": "他のアカウントを確認中", + "@verifyTitle": { + "type": "text", + "placeholders": {} + }, + "videoCall": "音声通話", + "@videoCall": { + "type": "text", + "placeholders": {} + }, + "visibilityOfTheChatHistory": "チャット履歴の表示", + "@visibilityOfTheChatHistory": { + "type": "text", + "placeholders": {} + }, + "visibleForAllParticipants": "すべての参加者が閲覧可能", + "@visibleForAllParticipants": { + "type": "text", + "placeholders": {} + }, + "visibleForEveryone": "すべての人が閲覧可能", + "@visibleForEveryone": { + "type": "text", + "placeholders": {} + }, + "voiceMessage": "ボイスメッセージ", + "@voiceMessage": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerAcceptRequest": "パートナーのリクエスト承諾待ちです...", + "@waitingPartnerAcceptRequest": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerEmoji": "パートナーの絵文字承諾待ちです...", + "@waitingPartnerEmoji": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerNumbers": "パートナーの数字承諾待ちです…", + "@waitingPartnerNumbers": { + "type": "text", + "placeholders": {} + }, + "wallpaper": "壁紙", + "@wallpaper": { + "type": "text", + "placeholders": {} + }, + "warning": "警告!", + "@warning": { + "type": "text", + "placeholders": {} + }, + "weSentYouAnEmail": "あなたにメールを送信しました", + "@weSentYouAnEmail": { + "type": "text", + "placeholders": {} + }, + "whoCanPerformWhichAction": "誰がどの操作を実行できるか", + "@whoCanPerformWhichAction": { + "type": "text", + "placeholders": {} + }, + "whoIsAllowedToJoinThisGroup": "誰がこのチャットに入れますか", + "@whoIsAllowedToJoinThisGroup": { + "type": "text", + "placeholders": {} + }, + "whyDoYouWantToReportThis": "これを通報する理由", + "@whyDoYouWantToReportThis": { + "type": "text", + "placeholders": {} + }, + "wipeChatBackup": "チャットのバックアップを消去して、新しいリカバリーキーを作りますか?", + "@wipeChatBackup": { + "type": "text", + "placeholders": {} + }, + "withTheseAddressesRecoveryDescription": "これらのアドレスを使用すると、パスワードを回復することができます。", + "@withTheseAddressesRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "writeAMessage": "メッセージを入力してください…", + "@writeAMessage": { + "type": "text", + "placeholders": {} + }, + "yes": "はい", + "@yes": { + "type": "text", + "placeholders": {} + }, + "you": "あなた", + "@you": { + "type": "text", + "placeholders": {} + }, + "youAreNoLongerParticipatingInThisChat": "あなたはもうこのチャットの参加者ではありません", + "@youAreNoLongerParticipatingInThisChat": { + "type": "text", + "placeholders": {} + }, + "youHaveBeenBannedFromThisChat": "チャットからBANされてしまいました", + "@youHaveBeenBannedFromThisChat": { + "type": "text", + "placeholders": {} + }, + "yourPublicKey": "あなたの公開鍵", + "@yourPublicKey": { + "type": "text", + "placeholders": {} + }, + "allChats": "すべて会話", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "addToSpace": "スペースに追加", + "@addToSpace": {}, + "cantOpenUri": "URIが開けません {uri}", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "repeatPassword": "パスワードを繰り返そ", + "@repeatPassword": {}, + "autoplayImages": "GIFを自動的に再生する", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "yourChatBackupHasBeenSetUp": "チャットバックアップを設定ました。", + "@yourChatBackupHasBeenSetUp": {}, + "sendOnEnter": "Enterで送信", + "@sendOnEnter": {}, + "changeYourAvatar": "アバタるを変化しする", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "chatHasBeenAddedToThisSpace": "このスペースにチャットが追加されました", + "@chatHasBeenAddedToThisSpace": {}, + "commandHint_ban": "このユーザーを禁止する", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_clearcache": "キャッシュをクリアする", + "@commandHint_clearcache": { + "type": "text", + "description": "Usage hint for the command /clearcache" + }, + "commandInvalid": "コマンドが無効", + "@commandInvalid": { + "type": "text" + }, + "commandHint_create": "空のグループチャットを作成\n暗号化を無効にするには、--no-encryption を使用", + "@commandHint_create": { + "type": "text", + "description": "Usage hint for the command /create" + }, + "commandHint_discardsession": "セッションを破棄", + "@commandHint_discardsession": { + "type": "text", + "description": "Usage hint for the command /discardsession" + }, + "confirmMatrixId": "アカウントを削除するには、Matrix IDを確認してください。", + "@confirmMatrixId": {}, + "commandHint_markasgroup": "グループとしてマーク", + "@commandHint_markasgroup": {}, + "commandHint_join": "指定した部屋に参加", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_send": "テキストを送信", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "hydrate": "バックアップファイルから復元", + "@hydrate": {}, + "commandHint_html": "HTML形式のテキストを送信", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_invite": "指定したユーザーをこの部屋に招待", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "commandMissing": "{command} はコマンドではありません。", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "oneClientLoggedOut": "クライアントの 1つがログアウトしました", + "@oneClientLoggedOut": {}, + "addAccount": "アカウントを追加", + "@addAccount": {}, + "editBundlesForAccount": "このアカウントのバンドルを編集", + "@editBundlesForAccount": {}, + "unverified": "未検証", + "@unverified": {}, + "sender": "送信者", + "@sender": {}, + "placeCall": "電話をかける", + "@placeCall": {}, + "voiceCall": "音声通話", + "@voiceCall": {}, + "unsupportedAndroidVersionLong": "この機能を利用するには、より新しいAndroidのバージョンが必要です。アップデートまたはLineage OSのサポートをご確認ください。", + "@unsupportedAndroidVersionLong": {}, + "widgetVideo": "動画", + "@widgetVideo": {}, + "widgetName": "名称", + "@widgetName": {}, + "widgetCustom": "カスタム", + "@widgetCustom": {}, + "widgetJitsi": "Jitsi Meet", + "@widgetJitsi": {}, + "dehydrateWarning": "この操作は元に戻せません。バックアップファイルを安全に保存してください。", + "@dehydrateWarning": {}, + "dehydrate": "セッションのエクスポートとデバイスの消去", + "@dehydrate": {}, + "messageType": "メッセージの種類", + "@messageType": {}, + "start": "開始", + "@start": {}, + "publish": "公開", + "@publish": {}, + "indexedDbErrorTitle": "プライベートモードに関する問題", + "@indexedDbErrorTitle": {}, + "addWidget": "ウィジェットを追加", + "@addWidget": {}, + "youBannedUser": "{user} を禁止しました", + "@youBannedUser": { + "placeholders": { + "user": {} + } + }, + "youJoinedTheChat": "チャットに参加しました", + "@youJoinedTheChat": {}, + "youHaveWithdrawnTheInvitationFor": "{user} への招待を取り下げました", + "@youHaveWithdrawnTheInvitationFor": { + "placeholders": { + "user": {} + } + }, + "users": "ユーザー", + "@users": {}, + "youRejectedTheInvitation": "招待を拒否しました", + "@youRejectedTheInvitation": {}, + "screenSharingDetail": "FuffyChatで画面を共有しています", + "@screenSharingDetail": {}, + "homeserver": "ホームサーバー", + "@homeserver": {}, + "scanQrCode": "QRコードをスキャン", + "@scanQrCode": {}, + "obtainingLocation": "位置情報を取得しています…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "addToBundle": "バンドルに追加", + "@addToBundle": {}, + "removeFromBundle": "このバンドルから削除", + "@removeFromBundle": {}, + "bundleName": "バンドル名", + "@bundleName": {}, + "noMatrixServer": "{server1} はMatrixのサーバーではありません。代わりに {server2} を使用しますか?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "openVideoCamera": "ビデオ用にカメラを開く", + "@openVideoCamera": { + "type": "text", + "placeholders": {} + }, + "link": "リンク", + "@link": {}, + "or": "または", + "@or": { + "type": "text", + "placeholders": {} + }, + "register": "登録", + "@register": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "アバターを削除する", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "saveFile": "ファイルを保存", + "@saveFile": { + "type": "text", + "placeholders": {} + }, + "recoveryKey": "リカバリーキー", + "@recoveryKey": {}, + "singlesignon": "シングルサインオン", + "@singlesignon": { + "type": "text", + "placeholders": {} + }, + "spaceIsPublic": "スペースは公開されています", + "@spaceIsPublic": { + "type": "text", + "placeholders": {} + }, + "spaceName": "スペース名", + "@spaceName": { + "type": "text", + "placeholders": {} + }, + "startFirstChat": "最初のチャットを開始する", + "@startFirstChat": {}, + "addToSpaceDescription": "このチャットを追加するスペースを選択してください。", + "@addToSpaceDescription": {}, + "messageInfo": "メッセージの情報", + "@messageInfo": {}, + "openGallery": "ギャラリーを開く", + "@openGallery": {}, + "removeFromSpace": "スペースから削除", + "@removeFromSpace": {}, + "pleaseEnterRecoveryKeyDescription": "古いメッセージを解除するには、以前のセッションで生成されたリカバリーキーを入力してください。リカバリーキーはパスワードではありません。", + "@pleaseEnterRecoveryKeyDescription": {}, + "videoWithSize": "ビデオ ({size})", + "@videoWithSize": { + "type": "text", + "placeholders": { + "size": {} + } + }, + "openChat": "チャットを開く", + "@openChat": {}, + "experimentalVideoCalls": "実験的なビデオ通話", + "@experimentalVideoCalls": {}, + "emailOrUsername": "メールアドレスまたはユーザー名", + "@emailOrUsername": {}, + "switchToAccount": "アカウント {number} に切り替える", + "@switchToAccount": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "nextAccount": "次のアカウント", + "@nextAccount": {}, + "youAcceptedTheInvitation": "👍 招待を承諾しました", + "@youAcceptedTheInvitation": {}, + "errorAddingWidget": "ウィジェットの追加中にエラーが発生しました。", + "@errorAddingWidget": {}, + "widgetNameError": "表示名を入力してください。", + "@widgetNameError": {}, + "youUnbannedUser": "{user} の禁止を解除しました", + "@youUnbannedUser": { + "placeholders": { + "user": {} + } + }, + "youInvitedBy": "📩 {user} から招待されました", + "@youInvitedBy": { + "placeholders": { + "user": {} + } + }, + "youKicked": "👞 {user} をキックしました", + "@youKicked": { + "placeholders": { + "user": {} + } + }, + "youKickedAndBanned": "🙅 {user} をキックしてブロックしました", + "@youKickedAndBanned": { + "placeholders": { + "user": {} + } + }, + "storeInAppleKeyChain": "Apple KeyChainに保存", + "@storeInAppleKeyChain": {}, + "storeInAndroidKeystore": "Android KeyStoreに保存する", + "@storeInAndroidKeystore": {}, + "storeInSecureStorageDescription": "このデバイスの安全なストレージにリカバリーキーを保存。", + "@storeInSecureStorageDescription": {}, + "unlockOldMessages": "古いメッセージのロックを解除する", + "@unlockOldMessages": {}, + "callingAccount": "通話アカウント", + "@callingAccount": {}, + "callingPermissions": "通話の権限", + "@callingPermissions": {}, + "screenSharingTitle": "画面共有", + "@screenSharingTitle": {}, + "foregroundServiceRunning": "この通知は、フォアグラウンド サービスの実行中に表示されます。", + "@foregroundServiceRunning": {}, + "custom": "カスタム", + "@custom": {}, + "countFiles": "{count}個のファイル", + "@countFiles": { + "placeholders": { + "count": {} + } + }, + "storeSecurlyOnThisDevice": "このデバイスに安全に保管する", + "@storeSecurlyOnThisDevice": {}, + "whyIsThisMessageEncrypted": "このメッセージが読めない理由", + "@whyIsThisMessageEncrypted": {}, + "otherCallingPermissions": "マイク、カメラ、その他FluffyChatの権限", + "@otherCallingPermissions": {}, + "appearOnTopDetails": "アプリをトップに表示できるようにする(すでに通話アカウントとしてFluffychatを設定している場合は必要ありません)", + "@appearOnTopDetails": {}, + "dehydrateTorLong": "TOR ユーザーの場合、ウィンドウを閉じる前にセッションをエクスポートすることをお勧めします。", + "@dehydrateTorLong": {}, + "hydrateTorLong": "前回、TOR でセッションをエクスポートしましたか?すぐにインポートしてチャットを続けましょう。", + "@hydrateTorLong": {}, + "enableMultiAccounts": "(ベータ版) このデバイスで複数のアカウントを有効にする", + "@enableMultiAccounts": {}, + "pleaseEnterRecoveryKey": "リカバリーキーを入力してください。", + "@pleaseEnterRecoveryKey": {}, + "serverRequiresEmail": "このサーバーは、登録のためにメールアドレスを検証する必要があります。", + "@serverRequiresEmail": {}, + "sendSticker": "ステッカーを送る", + "@sendSticker": { + "type": "text", + "placeholders": {} + }, + "synchronizingPleaseWait": "同期中...お待ちください。", + "@synchronizingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "emojis": "絵文字", + "@emojis": {}, + "markAsRead": "既読にする", + "@markAsRead": {}, + "videoCallsBetaWarning": "ビデオ通話は、現在ベータ版であることにご注意ください。すべてのプラットフォームで期待通りに動作しない、あるいはまったく動作しない可能性があります。", + "@videoCallsBetaWarning": {}, + "confirmEventUnpin": "イベントの固定を完全に解除してもよろしいですか?", + "@confirmEventUnpin": {}, + "unsupportedAndroidVersion": "サポートされていないAndroidのバージョン", + "@unsupportedAndroidVersion": {}, + "user": "ユーザー", + "@user": {}, + "newGroup": "新しいグループ", + "@newGroup": {}, + "noBackupWarning": "警告!チャットのバックアップを有効にしないと、暗号化されたメッセージにアクセスできなくなります。ログアウトする前に、まずチャットのバックアップを有効にすることを強くお勧めします。", + "@noBackupWarning": {}, + "disableEncryptionWarning": "セキュリティ上の理由から、以前は暗号化が有効だったチャットで暗号化を無効にすることはできません。", + "@disableEncryptionWarning": {}, + "youInvitedUser": "📩 {user} を招待しました", + "@youInvitedUser": { + "placeholders": { + "user": {} + } + }, + "reactedWith": "{sender} が {reaction} で反応しました", + "@reactedWith": { + "type": "text", + "placeholders": { + "sender": {}, + "reaction": {} + } + }, + "createNewSpace": "新しいスペース", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "widgetUrlError": "有効なURLではありません。", + "@widgetUrlError": {}, + "reportUser": "ユーザーを報告", + "@reportUser": {}, + "errorObtainingLocation": "位置情報の取得中にエラーが発生しました: {error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "pinMessage": "部屋にピン留めする", + "@pinMessage": {}, + "previousAccount": "前のアカウント", + "@previousAccount": {}, + "pleaseChoose": "選択してください", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "おっと!残念ながら、プッシュ通知の設定中にエラーが発生しました。", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "noOtherDevicesFound": "他のデバイスが見つかりません", + "@noOtherDevicesFound": {}, + "recoveryKeyLost": "リカバリーキーを紛失した場合", + "@recoveryKeyLost": {}, + "shareLocation": "位置情報の共有", + "@shareLocation": { + "type": "text", + "placeholders": {} + }, + "time": "時間", + "@time": {}, + "sendAsText": "テキストとして送信", + "@sendAsText": { + "type": "text" + }, + "commandHint_googly": "ぎょろ目を送る", + "@commandHint_googly": {}, + "commandHint_hug": "ハグを送る", + "@commandHint_hug": {}, + "encryptThisChat": "このチャットを暗号化する", + "@encryptThisChat": {}, + "commandHint_markasdm": "ダイレクトメッセージの部屋としてマークする", + "@commandHint_markasdm": {}, + "commandHint_dm": "ダイレクトチャットを開始する\n暗号化を無効にするには、--no-encryptionを使用してください", + "@commandHint_dm": { + "type": "text", + "description": "Usage hint for the command /dm" + }, + "commandHint_leave": "この部屋を退出", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_myroomavatar": "この部屋の写真を設定する (mxc-uriで)", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_myroomnick": "この部屋の表示名を設定する", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "commandHint_plain": "書式設定されていないテキストを送信する", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_react": "リアクションとして返信を送信する", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "dehydrateTor": "TOR ユーザー: セッションをエクスポート", + "@dehydrateTor": {}, + "hydrateTor": "TOR ユーザー: セッションのエクスポートをインポート", + "@hydrateTor": {}, + "locationDisabledNotice": "位置情報サービスが無効になっています。位置情報を共有できるようにするには、位置情報サービスを有効にしてください。", + "@locationDisabledNotice": { + "type": "text", + "placeholders": {} + }, + "locationPermissionDeniedNotice": "位置情報の権限が拒否されました。位置情報を共有できるように許可してください。", + "@locationPermissionDeniedNotice": { + "type": "text", + "placeholders": {} + }, + "deviceKeys": "デバイスキー:", + "@deviceKeys": {}, + "sorryThatsNotPossible": "申し訳ありません...それは不可能です", + "@sorryThatsNotPossible": {}, + "wasDirectChatDisplayName": "空のチャット (以前は {oldDisplayName})", + "@wasDirectChatDisplayName": { + "type": "text", + "placeholders": { + "oldDisplayName": {} + } + }, + "doNotShowAgain": "今後表示しない", + "@doNotShowAgain": {}, + "hideUnimportantStateEvents": "重要でない状態イベントを非表示にする", + "@hideUnimportantStateEvents": {}, + "numChats": "{number} チャット", + "@numChats": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "allSpaces": "すべてのスペース", + "@allSpaces": {}, + "enterRoom": "部屋に入る", + "@enterRoom": {}, + "enterSpace": "スペースに入る", + "@enterSpace": {}, + "newSpace": "新しいスペース", + "@newSpace": {}, + "reopenChat": "チャットを再開する", + "@reopenChat": {}, + "signInWith": "{provider}でログイン", + "@signInWith": { + "type": "text", + "placeholders": { + "provider": {} + } + }, + "signInWithPassword": "パスワードでログイン", + "@signInWithPassword": {} +} diff --git a/assets/l10n/intl_ko.arb b/assets/l10n/intl_ko.arb index 4e47d233d..ce17351d6 100644 --- a/assets/l10n/intl_ko.arb +++ b/assets/l10n/intl_ko.arb @@ -99,17 +99,17 @@ "type": "text", "placeholders": {} }, - "groups": "그룹", + "groups": "그룹 채팅", "@groups": { "type": "text", "placeholders": {} }, - "groupIsPublic": "그룹 공개됨", + "groupIsPublic": "그룹 채팅 공개됨", "@groupIsPublic": { "type": "text", "placeholders": {} }, - "group": "그룹", + "group": "그룹 채팅", "@group": { "type": "text", "placeholders": {} @@ -369,17 +369,17 @@ "type": "text", "placeholders": {} }, - "containsUserName": "유저 이름 포함", + "containsUserName": "내 아이디 포함", "@containsUserName": { "type": "text", "placeholders": {} }, - "containsDisplayName": "표시 이름 포함", + "containsDisplayName": "내 닉네임 포함", "@containsDisplayName": { "type": "text", "placeholders": {} }, - "contactHasBeenInvitedToTheGroup": "연락처가 그룹에 초대되었습니다", + "contactHasBeenInvitedToTheGroup": "연락처가 채팅에 초대되었습니다", "@contactHasBeenInvitedToTheGroup": { "type": "text", "placeholders": {} @@ -495,7 +495,7 @@ "type": "text", "placeholders": {} }, - "changeTheNameOfTheGroup": "그룹의 이름 바꾸기", + "changeTheNameOfTheGroup": "채팅의 이름 바꾸기", "@changeTheNameOfTheGroup": { "type": "text", "placeholders": {} @@ -727,7 +727,7 @@ "type": "text", "placeholders": {} }, - "answeredTheCall": "{senderName} 가 전화에 응답했습니다", + "answeredTheCall": "{senderName}님이 전화에 응답했습니다", "@answeredTheCall": { "type": "text", "placeholders": { @@ -808,12 +808,12 @@ "targetName": {} } }, - "guestsAreForbidden": "게스트는 금지되어 있습니다", + "guestsAreForbidden": "게스트가 들어올 수 없음", "@guestsAreForbidden": { "type": "text", "placeholders": {} }, - "groupWith": "{displayname} 과의 그룹", + "groupWith": "{displayname}님과의 그룹", "@groupWith": { "type": "text", "placeholders": { @@ -892,7 +892,7 @@ "type": "text", "placeholders": {} }, - "whoIsAllowedToJoinThisGroup": "누가 이 그룹에 들어오도록 허용할지", + "whoIsAllowedToJoinThisGroup": "누가 이 그룹 채팅에 들어오도록 허용할지", "@whoIsAllowedToJoinThisGroup": { "type": "text", "placeholders": {} @@ -1723,7 +1723,7 @@ "username": {} } }, - "isTyping": "가 입력 중…", + "isTyping": "입력 중…", "@isTyping": { "type": "text", "placeholders": {} @@ -1736,7 +1736,7 @@ "link": {} } }, - "inviteForMe": "나를 위해 초대", + "inviteForMe": "초대됨", "@inviteForMe": { "type": "text", "placeholders": {} @@ -1759,7 +1759,7 @@ "type": "text", "placeholders": {} }, - "inviteContactToGroup": "연락처 {groupName} 에 초대", + "inviteContactToGroup": "연락처를 {groupName}에 초대", "@inviteContactToGroup": { "type": "text", "placeholders": { @@ -1975,7 +1975,7 @@ "type": "text", "description": "Usage hint for the command /clearcache" }, - "commandHint_create": "빈 그룹 채팅을 생성\t\n--no-encryption을 사용해 암호화를 비활성화", + "commandHint_create": "빈 그룹 채팅을 생성\n--no-encryption을 사용해 암호화를 비활성화", "@commandHint_create": { "type": "text", "description": "Usage hint for the command /create" @@ -2041,7 +2041,7 @@ "senderName": {} } }, - "commandHint_markasgroup": "그룹으로 만들기", + "commandHint_markasgroup": "그룹 채팅으로 만들기", "@commandHint_markasgroup": {}, "dehydrate": "세션을 내보내고 기기 초기화 하기", "@dehydrate": {}, @@ -2092,7 +2092,7 @@ "@user": {}, "youAcceptedTheInvitation": "👍 초대를 수락했습니다", "@youAcceptedTheInvitation": {}, - "youInvitedBy": "📩 {user}에 의해 초대되었습니다", + "youInvitedBy": "📩 {user}님에 의해 초대되었습니다", "@youInvitedBy": { "placeholders": { "user": {} @@ -2104,14 +2104,14 @@ "@widgetEtherpad": {}, "removeDevicesDescription": "이 기기에서 로그아웃되며 더 이상 메시지를 받을 수 없습니다.", "@removeDevicesDescription": {}, - "separateChatTypes": "다이렉트 채팅 및 그룹 분리", + "separateChatTypes": "다이렉트 채팅과 그룹 채팅 분리", "@separateChatTypes": { "type": "text", "placeholders": {} }, "tryAgain": "다시 시도하기", "@tryAgain": {}, - "youKickedAndBanned": "🙅 {user}를 영구 추방했습니다", + "youKickedAndBanned": "🙅 {user}님을 영구 추방했습니다", "@youKickedAndBanned": { "placeholders": { "user": {} @@ -2237,7 +2237,7 @@ "reason": {} } }, - "youHaveWithdrawnTheInvitationFor": "{user}에 대한 초대를 철회함", + "youHaveWithdrawnTheInvitationFor": "{user}님에 대한 초대를 철회함", "@youHaveWithdrawnTheInvitationFor": { "placeholders": { "user": {} @@ -2247,7 +2247,7 @@ "@appearOnTopDetails": {}, "enterRoom": "방에 입장", "@enterRoom": {}, - "youInvitedUser": "📩 {user}를 초대했습니다", + "youInvitedUser": "📩 {user}님을 초대했습니다", "@youInvitedUser": { "placeholders": { "user": {} @@ -2278,7 +2278,7 @@ "@screenSharingTitle": {}, "widgetCustom": "사용자 정의", "@widgetCustom": {}, - "youBannedUser": "{user}을 영구 추방함", + "youBannedUser": "{user}님을 영구 추방함", "@youBannedUser": { "placeholders": { "user": {} @@ -2286,7 +2286,7 @@ }, "addChatDescription": "채팅 설명 추가하기...", "@addChatDescription": {}, - "hasKnocked": "🚪 {user}가 참가를 요청했습니다", + "hasKnocked": "🚪 {user}님이 참가를 요청했습니다", "@hasKnocked": { "placeholders": { "user": {} @@ -2334,7 +2334,7 @@ "@users": {}, "chatDescriptionHasBeenChanged": "채팅 설명 변경됨", "@chatDescriptionHasBeenChanged": {}, - "newGroup": "새 그룹", + "newGroup": "새 그룹 채팅", "@newGroup": {}, "dehydrateTor": "TOR 사용자: 세션 내보내기", "@dehydrateTor": {}, @@ -2342,7 +2342,7 @@ "@roomUpgradeDescription": {}, "pleaseEnterANumber": "0보다 큰 숫자를 입력하세요", "@pleaseEnterANumber": {}, - "youKicked": "👞 {user}를 추방했습니다", + "youKicked": "👞 {user}님을 추방했습니다", "@youKicked": { "placeholders": { "user": {} @@ -2386,7 +2386,7 @@ "@commandHint_hug": {}, "replace": "대체", "@replace": {}, - "youUnbannedUser": "{user}의 영구 추방을 해제했습니다", + "youUnbannedUser": "{user}님의 영구 추방을 해제했습니다", "@youUnbannedUser": { "placeholders": { "user": {} @@ -2396,11 +2396,11 @@ "@newSpace": {}, "pleaseTryAgainLaterOrChooseDifferentServer": "나중에 다시 시도하거나 다른 서버를 선택하십시오.", "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "createGroup": "그룹 만들기", + "createGroup": "새 그룹 채팅", "@createGroup": {}, "hydrateTorLong": "지난 TOR 이용에서 세션을 내보내셨나요? 빠르게 불러오고 채팅을 계속하세요.", "@hydrateTorLong": {}, - "custom": "개인화", + "custom": "커스텀", "@custom": {}, "noBackupWarning": "경고! 채팅 백업을 켜지 않을경우, 당신은 암호화된 메시지에대한 접근권한을 잃을것입니다. 로그아웃 하기 전에 채팅을 백업하는것이 강력히 권장됩니다.", "@noBackupWarning": {}, @@ -2424,7 +2424,7 @@ "@block": {}, "blockedUsers": "차단된 유저", "@blockedUsers": {}, - "groupName": "그룹 이름", + "groupName": "그룹 채팅 이름", "@groupName": {}, "commandHint_sendraw": "raw json 전송", "@commandHint_sendraw": {}, @@ -2464,7 +2464,7 @@ "sender": {} } }, - "createGroupAndInviteUsers": "그룹을 생성하고 유저를 초대", + "createGroupAndInviteUsers": "그룹 채팅을 생성하고 유저를 초대", "@createGroupAndInviteUsers": {}, "passwordsDoNotMatch": "비밀번호가 일치하지 않습니다", "@passwordsDoNotMatch": {}, @@ -2484,7 +2484,7 @@ "@hidePresences": {}, "searchChatsRooms": "#chats, @users 검색...", "@searchChatsRooms": {}, - "groupCanBeFoundViaSearch": "검색으로 그룹을 찾을 수 있음", + "groupCanBeFoundViaSearch": "검색으로 그룹 채팅을 찾을 수 있음", "@groupCanBeFoundViaSearch": {}, "restoreSessionBody": "앱이 백업에서 세션을 복원하려 시도중입니다. {url} 에서 개발자에게 오류를 신고하세요. 오류 메시지는 다음과 같습니다: {error}", "@restoreSessionBody": { @@ -2622,13 +2622,13 @@ "@calls": {}, "globalChatId": "글로벌 채팅 ID", "@globalChatId": {}, - "customEmojisAndStickers": "개인 이모지와 스티커", + "customEmojisAndStickers": "커스텀 이모지와 스티커", "@customEmojisAndStickers": {}, - "accessAndVisibilityDescription": "채팅에 참여하거나 찾을 수 있는 사람을 설정합니다.", + "accessAndVisibilityDescription": "채팅에 참여 할 수 있는 사람과 채팅을 볼 수 있는 범위", "@accessAndVisibilityDescription": {}, - "accessAndVisibility": "방 가입과 대화 기록", + "accessAndVisibility": "채팅 가입과 대화 기록", "@accessAndVisibility": {}, - "customEmojisAndStickersBody": "모든 채팅에서 사용할 수있는 개인 이모지와 스티커를 추가하거나 공유합니다.", + "customEmojisAndStickersBody": "모든 채팅에서 사용할 수있는 커스텀 이모지와 스티커를 추가하거나 공유합니다.", "@customEmojisAndStickersBody": {}, "hideRedactedMessages": "삭제된 메시지 숨기기", "@hideRedactedMessages": {}, @@ -2644,7 +2644,7 @@ "@passwordRecoverySettings": {}, "hideMemberChangesInPublicChats": "공개 채팅에서의 참가자 변화 숨김", "@hideMemberChangesInPublicChats": {}, - "userWouldLikeToChangeTheChat": "{user}가 참가를 희망합니다.", + "userWouldLikeToChangeTheChat": "{user}님이 참가를 희망합니다.", "@userWouldLikeToChangeTheChat": { "placeholders": { "user": {} @@ -2667,7 +2667,7 @@ }, "noOneCanJoin": "아무도 들어올 수 없음", "@noOneCanJoin": {}, - "thereAreCountUsersBlocked": "여기 {count}명의 차단된 유저가 있습니다.", + "thereAreCountUsersBlocked": "{count}명의 차단된 유저가 있습니다.", "@thereAreCountUsersBlocked": { "type": "text", "count": {} @@ -2701,5 +2701,40 @@ } }, "gallery": "갤러리", - "@gallery": {} + "@gallery": {}, + "restricted": "스페이스 멤버로 제한", + "@restricted": {}, + "knockRestricted": "스페이스 멤버만 참가 요청 가능", + "@knockRestricted": {}, + "swipeRightToLeftToReply": "오른쪽에서 왼쪽으로 스와이프해서 답장", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "false", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "unread": "읽지 않은", + "@unread": {}, + "space": "스페이스", + "@space": {}, + "spaces": "스페이스", + "@spaces": {}, + "goToSpace": "스페이스로: {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "읽지 않음으로 표시", + "@markAsUnread": {}, + "countChatsAndCountParticipants": "{chats} 채팅과 {participants} 참여자", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "joinedChats": "참여한 채팅", + "@joinedChats": {}, + "noMoreChatsFound": "채팅을 찾을 수 없습니다...", + "@noMoreChatsFound": {} } diff --git a/assets/l10n/intl_lt.arb b/assets/l10n/intl_lt.arb index 0a77ba065..0a45a29e2 100644 --- a/assets/l10n/intl_lt.arb +++ b/assets/l10n/intl_lt.arb @@ -1,2347 +1,2218 @@ { - "commandHint_leave": "Palikti pokalbių kambarį", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "confirm": "Patvirtinti", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "cancel": "Atšaukti", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "edit": "Redaguoti", - "@edit": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "Atsisiųsti failą", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "about": "Apie", - "@about": { - "type": "text", - "placeholders": {} - }, - "all": "Visi", - "@all": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "fileName": "Failo vardas", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "changePassword": "Keisti slaptažodį", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "close": "Uždaryti", - "@close": { - "type": "text", - "placeholders": {} - }, - "archive": "Archyvas", - "@archive": { - "type": "text", - "placeholders": {} - }, - "skip": "Praleisti", - "@skip": { - "type": "text", - "placeholders": {} - }, - "share": "Bendrinti", - "@share": { - "type": "text", - "placeholders": {} - }, - "showPassword": "Rodyti slaptažodį", - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "time": "Laikas", - "@time": {}, - "settings": "Nustatytmai", - "@settings": { - "type": "text", - "placeholders": {} - }, - "sender": "Siuntėjas", - "@sender": {}, - "yes": "Taip", - "@yes": { - "type": "text", - "placeholders": {} - }, - "you": "Jūs", - "@you": { - "type": "text", - "placeholders": {} - }, - "logout": "Atsijungti", - "@logout": { - "type": "text", - "placeholders": {} - }, - "messages": "Žinutės", - "@messages": { - "type": "text", - "placeholders": {} - }, - "scanQrCode": "Nuskanuokite QR kodą", - "@scanQrCode": {}, - "ok": "OK", - "@ok": { - "type": "text", - "placeholders": {} - }, - "addAccount": "Pridėti paskyrą", - "@addAccount": {}, - "or": "Arba", - "@or": { - "type": "text", - "placeholders": {} - }, - "password": "Slaptažodis", - "@password": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "Slaptažodis pakeistas", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "Įveskite savo slaptažodį", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "Įveskite savo vartotojo vardą", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "reply": "Atsakyti", - "@reply": { - "type": "text", - "placeholders": {} - }, - "blockDevice": "Blokuoti įrenginį", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "Užblokuotas", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "Pasirinkite saugų slaptažodį", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "Ištrinti žinutę", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "device": "Įrenginys", - "@device": { - "type": "text", - "placeholders": {} - }, - "deviceId": "Įrenginio ID", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "Įrenginiai", - "@devices": { - "type": "text", - "placeholders": {} - }, - "homeserver": "Namų serveris", - "@homeserver": {}, - "enterYourHomeserver": "Įveskite namų serverį", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "everythingReady": "Viskas paruošta!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "fontSize": "Šrifto dydis", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "Išvalyti archyvą", - "@clearArchive": {}, - "create": "Sukurti", - "@create": { - "type": "text", - "placeholders": {} - }, - "connect": "Prisijungti", - "@connect": { - "type": "text", - "placeholders": {} - }, - "people": "Žmonės", - "@people": { - "type": "text", - "placeholders": {} - }, - "moderator": "Moderatorius", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "muteChat": "Nutildyti pokalbį", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "newChat": "Naujas pokalbis", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "none": "Nė vienas", - "@none": { - "type": "text", - "placeholders": {} - }, - "noPermission": "Nėra leidimo", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "Nerasta kambarių…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "notifications": "Pranešimai", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "notificationsEnabledForThisAccount": "Pranešimai aktyvuoti šitai paskyrai", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "obtainingLocation": "Gaunama vieta…", - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "offensive": "Agresyvus", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "offline": "Neprisijungta", - "@offline": { - "type": "text", - "placeholders": {} - }, - "online": "Prisijungta", - "@online": { - "type": "text", - "placeholders": {} - }, - "oopsPushError": "Oi! Deja, nustatant tiesioginius pranešimus įvyko klaida.", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "Oi, kažkas nutiko ne taip…", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "Atidarykite programėlę, kad perskaityti žinutes", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "link": "Nuoroda", - "@link": {}, - "participant": "Dalyvis", - "@participant": { - "type": "text", - "placeholders": {} - }, - "passphraseOrKey": "Slapta frazė arba atkūrimo raktas", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "Slaptažodis užmirštas", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "passwordRecovery": "Slaptažodžio atkūrimas", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "pickImage": "Pasirinkite paveiksliuką", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "pin": "Prisegti", - "@pin": { - "type": "text", - "placeholders": {} - }, - "pleaseChoose": "Prašome pasirinkti", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "pleaseChooseAPasscode": "Pasirinkite slaptą kodą", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pleaseClickOnLink": "Paspauskite nuorodą el. pašte ir tęskite toliau.", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "Įveskite 4 skaitmenis arba palikite tuščią, jei norite išjungti programėlės užraktą.", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "Įveskite savo PIN kodą", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "pleaseFollowInstructionsOnWeb": "Vadovaukitės svetainėje pateiktais nurodymais ir bakstelėkite Toliau.", - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "privacy": "Privatumas", - "@privacy": { - "type": "text", - "placeholders": {} - }, - "publicRooms": "Vieši kambariai", - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "reason": "Priežastis", - "@reason": { - "type": "text", - "placeholders": {} - }, - "recording": "Įrašymas", - "@recording": { - "type": "text", - "placeholders": {} - }, - "redactMessage": "Pašalinti žinutę", - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "register": "Registruotis", - "@register": { - "type": "text", - "placeholders": {} - }, - "reject": "Atmesti", - "@reject": { - "type": "text", - "placeholders": {} - }, - "rejoin": "Vėl prisijungti", - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "remove": "Pašalinti", - "@remove": { - "type": "text", - "placeholders": {} - }, - "removeAllOtherDevices": "Pašalinti visus kitus įrenginius", - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "removeDevice": "Pašalinti įrenginį", - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "removeYourAvatar": "Pašalinti savo avatarą", - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "replaceRoomWithNewerVersion": "Pakeisti kambarį naujesne versija", - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "requestPermission": "Prašyti leidimo", - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "roomHasBeenUpgraded": "Kambarys buvo atnaujintas", - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "roomVersion": "Kambario versija", - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "search": "Ieškoti", - "@search": { - "type": "text", - "placeholders": {} - }, - "accept": "Sutinku", - "@accept": { - "type": "text", - "placeholders": {} - }, - "repeatPassword": "Pakartokite slaptažodį", - "@repeatPassword": {}, - "addEmail": "Pridėti el. paštą", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "admin": "Administratorius", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "slapyvardis", - "@alias": { - "type": "text", - "placeholders": {} - }, - "allChats": "Visi pokalbiai", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "anyoneCanJoin": "Bet kas gali prisijungti", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "Ar esate tikri?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "areYouSureYouWantToLogout": "Ar tikrai norite atsijungti?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "changeTheHomeserver": "Pakeisti namų serverį", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "Keisti savo stilių", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "Keisti grupės pavadinimą", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "Keisti savo avatarą", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "chat": "Pokalbis", - "@chat": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "Pokalbio detalės", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chats": "Pokalbiai", - "@chats": { - "type": "text", - "placeholders": {} - }, - "commandHint_ban": "Užblokuoti vartotoją šiame kambaryje", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_clearcache": "Išvalyti laikiną talpyklą", - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "commandHint_discardsession": "Atmesti sesiją", - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "commandHint_html": "Siųsti tekstą HTML formatu", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "Pakviesti vartotoją į šitą kambarį", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_join": "Prisijungti prie nurodyto kambario", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_kick": "Pašalinti vartotoja iš šito kambario", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_myroomnick": "Nustatyti savo rodomą vardą šiame kambaryje", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_plain": "Siųsti neformatuotą tekstą", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_send": "Siųsti tekstą", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandHint_unban": "Atblokuoti vartotoją šiame kambaryje", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "commandInvalid": "Neteisinga komanda", - "@commandInvalid": { - "type": "text" - }, - "configureChat": "Konfigūruoti pokalbį", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "Nukopijuota į iškarpinę", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "copy": "Kopijuoti", - "@copy": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "Koipjuoti į iškarpinę", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "currentlyActive": "Šiuo metu aktyvus", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "Tamsi", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "delete": "Ištrinti", - "@delete": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "Panaikinti paskyra", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "directChats": "Tiesioginiai pokalbiai", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "encrypted": "Užšifruotas", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "encryptionNotEnabled": "Šifravimas aktyvuotas", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "enterAnEmailAddress": "Įveskite el. pašto adresą", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "Itin įžeidžiantis", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "forward": "Toliau", - "@forward": { - "type": "text", - "placeholders": {} - }, - "fromJoining": "Nuo prisijungimo", - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "fromTheInvitation": "Nuo pakvietimo", - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "goToTheNewRoom": "Eiti į naują kambarį", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "group": "Grupė", - "@group": { - "type": "text", - "placeholders": {} - }, - "groupIsPublic": "Grupė yra vieša", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "groups": "Grupės", - "@groups": { - "type": "text", - "placeholders": {} - }, - "guestsAreForbidden": "Svečiams draudžiama", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "Svečiai gali prisijungti", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "help": "Pagalba", - "@help": { - "type": "text", - "placeholders": {} - }, - "hideRedactedEvents": "Slėpti pašalintus įvykius", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "Slėpti nežinomus įvykius", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "identity": "Tapatybė", - "@identity": { - "type": "text", - "placeholders": {} - }, - "ignore": "Ignoruoti", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "Ignoruoti vartotojai", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "leave": "Palikti", - "@leave": { - "type": "text", - "placeholders": {} - }, - "memberChanges": "Narių pokyčiai", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "mention": "Paminėti", - "@mention": { - "type": "text", - "placeholders": {} - }, - "encryption": "Šifravimas", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "Aktyvuoti šifravimą", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "Redaguoti blokuotus serverius", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "login": "Prisijungti", - "@login": { - "type": "text", - "placeholders": {} - }, - "sendOnEnter": "Išsiųsti paspaudus Enter", - "@sendOnEnter": {}, - "banFromChat": "Užblokuoti iš pokalbio", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "Užblokuotas", - "@banned": { - "type": "text", - "placeholders": {} - }, - "changeDeviceName": "Pakeisti įrenginio vardą", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "yourChatBackupHasBeenSetUp": "Jūsų pokalbio atsarginė kopija buvo nustatyta.", - "@yourChatBackupHasBeenSetUp": {}, - "chatBackup": "Pokalbio atsargine kopija", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "commandHint_me": "Apibūdinkite save", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "displaynameHasBeenChanged": "Rodomas vardas buvo pakeistas", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "Redaguoti rodomą vardą", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "Redaguoti kambario pseudonimus", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "Redaguoti kambario avatarą", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "howOffensiveIsThisContent": "Kiek įžeižiantis šis turinys?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "id": "ID", - "@id": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "Aš paspaudžiau nuorodą", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "incorrectPassphraseOrKey": "Neteisinga slaptafrazė arba atkūrimo raktas", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "Neįžeidžiantis", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "Pakviesti kontaktą", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "invited": "Pakviestas", - "@invited": { - "type": "text", - "placeholders": {} - }, - "invitedUsersOnly": "Tik pakviesti vartotojai", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "isTyping": "rašo…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "joinRoom": "Prisijungti prie kambario", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "kickFromChat": "Išmesti iš pokalbio", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "leftTheChat": "Paliko pokalbį", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "license": "Licencija", - "@license": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "Šviesi", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "loadingPleaseWait": "Kraunama… Prašome palaukti.", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "loadMore": "Rodyti daugiau…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "💬 Nauja žinutė FluffyChat'e", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "newVerificationRequest": "Nauja patvirtinimo užklausa!", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "next": "Toliau", - "@next": { - "type": "text", - "placeholders": {} - }, - "no": "Ne", - "@no": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "Nėra ryšio su serveriu", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "setInvitationLink": "Nustatyti pakvietimo nuorodą", - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "singlesignon": "Vienkartinis prisijungimas", - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "sourceCode": "Programinis kodas", - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "spaceIsPublic": "Erdvė yra vieša", - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "spaceName": "Erdvės pavadinimas", - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "status": "Būsena", - "@status": { - "type": "text", - "placeholders": {} - }, - "statusExampleMessage": "Kaip sekasi šiandien?", - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "submit": "Pateikti", - "@submit": { - "type": "text", - "placeholders": {} - }, - "synchronizingPleaseWait": "Sinchronizuojama… Prašome palaukti.", - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "transferFromAnotherDevice": "Perkėlimas iš kito įrenginio", - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "verify": "Patvirtinti", - "@verify": { - "type": "text", - "placeholders": {} - }, - "verifyStart": "Pradėti patvirtinimą", - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "verifySuccess": "Jūs sėkmingai patvirtinote!", - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "verifyTitle": "Patvirtinama kita paskyra", - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "visibilityOfTheChatHistory": "Pokalbių istorijos matomumas", - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "visibleForAllParticipants": "Matoma visiems dalyviams", - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerAcceptRequest": "Laukiama, kol dalyvis priims užklausą…", - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "writeAMessage": "Rašyti žinutę…", - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "youAreNoLongerParticipatingInThisChat": "Jūs nebedalyvaujate šiame pokalbyje", - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "youHaveBeenBannedFromThisChat": "Jums buvo uždrausta dalyvauti šiame pokalbyje", - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "messageInfo": "Žinutės informacija", - "@messageInfo": {}, - "removeFromSpace": "Pašalinti iš erdvės", - "@removeFromSpace": {}, - "security": "Apsauga", - "@security": { - "type": "text", - "placeholders": {} - }, - "sendAsText": "Siųsti kaip tekstą", - "@sendAsText": { - "type": "text" - }, - "sendAudio": "Siųsti garso įrašą", - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "sendImage": "Siųsti paveiksliuką", - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "sendFile": "Sųsti bylą", - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "sendMessages": "Siųsti žinutes", - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "sendOriginal": "Siųsti originalą", - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "sendVideo": "Siųsti video", - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "separateChatTypes": "Atskirti tiesioginius pokalbius ir grupes", - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "setAsCanonicalAlias": "Nustatyti kaip pagrindinį slapyvardį", - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "setPermissionsLevel": "Nustatyti leidimų lygį", - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "setStatus": "Nustatyti būseną", - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "shareLocation": "Bendrinti vietą", - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "systemTheme": "Sistema", - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "unavailable": "Nepasiekiamas", - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "unblockDevice": "Atblokuoti įrenginį", - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "unknownEncryptionAlgorithm": "Nežinomas šifravimo algoritmas", - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "unmuteChat": "Įjungti pokalbio garsą", - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "unpin": "Atsegti", - "@unpin": { - "type": "text", - "placeholders": {} - }, - "username": "Vartotojo vardas", - "@username": { - "type": "text", - "placeholders": {} - }, - "unverified": "Nepatvirtinta", - "@unverified": {}, - "verified": "Patvirtinta", - "@verified": { - "type": "text", - "placeholders": {} - }, - "videoCall": "Vaizdo skambutis", - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "yourPublicKey": "Jūsų viešasis raktas", - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "addToSpaceDescription": "Pasirinkite erdvę, kad prie jos pridėtumėte šį pokalbį.", - "@addToSpaceDescription": {}, - "start": "Pradžia", - "@start": {}, - "account": "Paskyra", - "@account": { - "type": "text", - "placeholders": {} - }, - "addToSpace": "Pridėti į erdvę", - "@addToSpace": {}, - "appLock": "Programos užraktas", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "Ar svečiams leidžiama prisijungti", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "botMessages": "Botų žinutės", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "Šifravimas buvo sugadintas", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "Pokalbis buvo pridėtas prie šios erdvės", - "@chatHasBeenAddedToThisSpace": {}, - "compareEmojiMatch": "Palyginkite jaustukus", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Palyginkite skaičius", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "Kontaktas buvo pakviestas į grupę", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "Apie turinį pranešta serverio administratoriams", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "createNewSpace": "Nauja erdvė", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "deactivateAccountWarning": "Tai deaktyvuos jūsų vartotojo paskyrą. Tai negali būti atšaukta! Ar jūs tuo tikri?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "Numatytasis teisių lygis", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "enableEncryptionWarning": "Šifravimo nebegalėsite išjungti. Ar jūs tuo tikri?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "send": "Siųsti", - "@send": { - "type": "text", - "placeholders": {} - }, - "sendAMessage": "Siųsti žinutę", - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "toggleUnread": "Pažymėti kaip skaitytą/neskaitytą", - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "tooManyRequestsWarning": "Per daug užklausų. Pabandykite dar kartą vėliau!", - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerEmoji": "Laukiama, kol dalyvis priims jaustukus…", - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerNumbers": "Laukiama, kol dalyvis priims skaičius…", - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "wallpaper": "Užsklanda", - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "warning": "Įspėjimas!", - "@warning": { - "type": "text", - "placeholders": {} - }, - "weSentYouAnEmail": "Išsiuntėme jums el. laišką", - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "whoCanPerformWhichAction": "Kas gali atlikti kokį veiksmą", - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "whoIsAllowedToJoinThisGroup": "Kam leidžiama prisijungti prie šios grupės", - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "whyDoYouWantToReportThis": "Kodėl norite apie tai pranešti?", - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "wipeChatBackup": "Ištrinti atsarginę pokalbių kopiją, kad sukurti naują atkūrimo raktą?", - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "withTheseAddressesRecoveryDescription": "Naudodami šiuos adresus galite atkurti savo slaptažodį.", - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "messageType": "Žinutės tipas", - "@messageType": {}, - "openGallery": "Atverti galeriją", - "@openGallery": {}, - "unknownDevice": "Nežinomas įrenginys", - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "voiceMessage": "Balso žinutė", - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "title": "FluffyChat", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "visibleForEveryone": "Matoma visiems", - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "tryToSendAgain": "Pabandykite išsiųsti dar kartą", - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "locationPermissionDeniedNotice": "Vietos leidimas atmestas. Suteikite leidimą kad galėtumėte bendrinti savo vietą.", - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "Atminkite, kad norint naudoti end-to-end šifravimą, reikalingas Pantalaimon.", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "Šifravimą galite suaktyvinti tik tada, kai kambarys nebebus viešai pasiekiamas.", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "noEmotesFound": "Nerasta jaustukų. 😕", - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "noGoogleServicesWarning": "Atrodo, kad jūsų telefone nėra Google Services. Tai geras sprendimas jūsų privatumui! Norėdami gauti tiesioginius pranešimus FluffyChat, rekomenduojame naudoti https://microg.org/ arba https://unifiedpush.org/.", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "Dar nepridėjote slaptažodžio atkūrimo būdo.", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "oneClientLoggedOut": "Vienas iš jūsų klientų atsijungė", - "@oneClientLoggedOut": {}, - "onlineKeyBackupEnabled": "Internetinė atsarginė raktų kopija įjungta", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "openCamera": "Atidarykite kamerą", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "openVideoCamera": "Atidarykite kamerą vaizdo įrašui", - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "editBundlesForAccount": "Redaguoti šios paskyros paketus", - "@editBundlesForAccount": {}, - "serverRequiresEmail": "Šis serveris turi patvirtinti jūsų el. pašto adresą registracijai.", - "@serverRequiresEmail": {}, - "addToBundle": "Pridėti prie paketų", - "@addToBundle": {}, - "removeFromBundle": "Pašalinkite iš šio paketo", - "@removeFromBundle": {}, - "bundleName": "Paketo vardas", - "@bundleName": {}, - "play": "Groti {fileName}", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "redactedAnEvent": "{username} pašalino įvykį", - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "rejectedTheInvitation": "{username} atmetė kvietimą", - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removedBy": "Pašalino vartotojas {username}", - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "unbanFromChat": "Atblokuoti pokalbyje", - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "renderRichContent": "Atvaizduoti turtingą žinutės turinį", - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "reportMessage": "Pranešti apie žinutę", - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "saveFile": "Išsaugoti failą", - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "seenByUser": "Matė {username}", - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sendSticker": "Siųsti lipduką", - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "sentAFile": "📁 {username} atsiuntė failą", - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAnAudio": "🎤 {username} atsiuntė garso įrašą", - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentASticker": "😊 {username} atsiuntė lipduką", - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sharedTheLocation": "{username} bendrino savo vietą", - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "startedACall": "{senderName} pradėjo skambutį", - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "theyDontMatch": "Jie nesutampa", - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "theyMatch": "Jie sutampa", - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "unbannedUser": "{username} atblokavo {targetName}", - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "unknownEvent": "Nežinomas įvykis '{type}'", - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "userAndOthersAreTyping": "{username} ir dar {count} kiti rašo…", - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "userAndUserAreTyping": "{username} ir {username2} rašo…", - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "userIsTyping": "{username} rašo…", - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "userSentUnknownEvent": "{username} išsiuntė {type} įvykį", - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "publish": "Paskelbti", - "@publish": {}, - "openChat": "Atverti pokalbį", - "@openChat": {}, - "reportUser": "Pranešti apie vartotoją", - "@reportUser": {}, - "dismiss": "Atsisakyti", - "@dismiss": {}, - "reactedWith": "{sender} sureagavo su {reaction}", - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "unsupportedAndroidVersion": "Nepalaikoma Android versija", - "@unsupportedAndroidVersion": {}, - "emailOrUsername": "El. paštas arba vartotojo vardas", - "@emailOrUsername": {}, - "widgetVideo": "Video", - "@widgetVideo": {}, - "widgetNameError": "Pateikite rodomą vardą.", - "@widgetNameError": {}, - "acceptedTheInvitation": "👍 {username} priėmė kvietimą", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "activatedEndToEndEncryption": "🔐 {username} aktyvavo visapusį šifravimą", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "answeredTheCall": "{senderName} atsiliepė į skambutį", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "askVerificationRequest": "Priimti šią patvirtinimo užklausą iš {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "badServerLoginTypesException": "Namų serveris palaiko šiuos prisijungimo tipus:\n{serverVersions}\nTačiau ši programa palaiko tik:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "badServerVersionsException": "Namų serveris palaiko spec. versijas:\n{serverVersions}\nTačiau ši programa palaiko tik {supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "bannedUser": "{username} užblokavo {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "changedTheHistoryVisibility": "{username} pakeitė istorijos matomumą", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "{username} pakeitė istorijos matomumą į: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "chatBackupDescription": "Jūsų senos žinutės yra apsaugotos atkūrimo raktu. Pasirūpinkite, kad jo neprarastumėte.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "commandHint_create": "Sukurti tuščią grupinį pokalbį\nNaudokite --no-encryption kad išjungti šifravimą", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "commandHint_dm": "Pradėti tiesioginį pokalbį\nNaudokite --no-encryption kad išjungti šifravimą", - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "commandHint_myroomavatar": "Nustatyti savo nuotrauką šiame kambaryje (su mxc-uri)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_op": "Nustatyti naudotojo galios lygį (numatytasis: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_react": "Siųsti atsakymą kaip reakciją", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandMissing": "{command} nėra komanda.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "containsDisplayName": "Turi rodomą vardą", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "Turi vartotojo vardą", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Nepavyko iššifruoti pranešimo: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "countParticipants": "{count} dalyviai", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "createdTheChat": "💬 {username} sukūrė pokalbį", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "emptyChat": "Tuščias pokalbis", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Jaustukas jau egzistuoja!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "Neteisingas jaustuko trumpasis kodas!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "Jaustukų paketai kambariui", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Jaustukų nustatymai", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "emoteShortcode": "Jaustuko trumpasis kodas", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Turite pasirinkti jaustuko trumpąjį kodą ir paveiksliuką!", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "Įgalinti jaustukų paketą visur", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "{senderName} baigė skambutį", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "errorObtainingLocation": "Klaida nustatant vietą: {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "groupWith": "Grupė su {displayname}", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "hasWithdrawnTheInvitationFor": "{username} atšaukė {targetName} kvietimą", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "inviteForMe": "Pakvietimas man", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "Pakviesti kontaktą į {groupName}", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "invitedUser": "📩 {username} pakvietė {targetName}", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "inviteText": "{username} pakvietė jus prisijungti prie FluffyChat. \n1. Įdiekite FluffyChat: https://fluffychat.im \n2. Prisiregistruokite arba prisijunkite \n3. Atidarykite pakvietimo nuorodą: {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "joinedTheChat": "👋 {username} prisijungė prie pokalbio", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "kicked": "👞 {username} išmetė {targetName}", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickedAndBanned": "🙅 {username} išmetė ir užblokavo {targetName}", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "lastActiveAgo": "Paskutinis aktyvumas: {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "loadCountMoreParticipants": "Įkelti dar {count} dalyvius", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "logInTo": "Prisijungti prie {homeserver}", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "toggleFavorite": "Perjungti parankinius", - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "toggleMuted": "Perjungti nutildytą", - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "cantOpenUri": "Nepavyksta atidaryti URI {uri}", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "changedTheChatAvatar": "{username} pakeitė pokalbio avatarą", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatDescriptionTo": "{username} pakeitė pokalbio aprašymą į: '{description}'", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheChatNameTo": "{username} pakeitė pokalbio pavadinimą į: '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheChatPermissions": "{username} pakeitė pokalbių leidimus", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "{username} pakeitė rodomą vardą į: '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRules": "{username} pakeitė svečio prieigos taisykles", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} pakeitė svečio prieigos taisykles į: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username} pakeitė prisijungimo taisykles", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "{username} pakeitė prisijungimo taisykles į: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheProfileAvatar": "{username} pakeitė savo avatarą", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "{username} pakeitė kambario pseudonimus", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomInvitationLink": "{username} pakeitė pakvietimo nuorodą", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "videoWithSize": "Vaizdo įrašas ({size})", - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "pinMessage": "Prisegti prie kambario", - "@pinMessage": {}, - "confirmEventUnpin": "Ar tikrai norite visam laikui atsegti įvykį?", - "@confirmEventUnpin": {}, - "emojis": "Jaustukai", - "@emojis": {}, - "placeCall": "Skambinti", - "@placeCall": {}, - "voiceCall": "Balso skambutis", - "@voiceCall": {}, - "unsupportedAndroidVersionLong": "Šiai funkcijai reikalinga naujesnė Android versija. Patikrinkite, ar nėra naujinimų arba Lineage OS palaikymo.", - "@unsupportedAndroidVersionLong": {}, - "videoCallsBetaWarning": "Atminkite, kad vaizdo skambučiai šiuo metu yra beta versijos. Jie gali neveikti taip kaip tikėtasi, arba iš viso neveikti visose platformose.", - "@videoCallsBetaWarning": {}, - "experimentalVideoCalls": "Eksperimentiniai vaizdo skambučiai", - "@experimentalVideoCalls": {}, - "switchToAccount": "Perjungti paskyrą į {number}", - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "nextAccount": "Kita paskyra", - "@nextAccount": {}, - "previousAccount": "Ankstesnė paskyra", - "@previousAccount": {}, - "widgetEtherpad": "Teksto pastaba", - "@widgetEtherpad": {}, - "widgetJitsi": "Jitsi Meet", - "@widgetJitsi": {}, - "widgetName": "Vardas", - "@widgetName": {}, - "widgetUrlError": "Netinkamas URL.", - "@widgetUrlError": {}, - "youRejectedTheInvitation": "Jūs atmetėte kvietimą", - "@youRejectedTheInvitation": {}, - "youJoinedTheChat": "Jūs prisijungėte prie pokalbio", - "@youJoinedTheChat": {}, - "youAcceptedTheInvitation": "👍 Jūs priėmėte kvietimą", - "@youAcceptedTheInvitation": {}, - "youBannedUser": "Jūs užblokavote {user}", - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "youHaveWithdrawnTheInvitationFor": "Jūs atšaukėte kvietimą {user}", - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "youInvitedBy": "📩 Jus pakvietė {user}", - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "youKicked": "👞 Jūs išmetėte {user}", - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "youInvitedUser": "📩 Pakvietėte {user}", - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "youKickedAndBanned": "🙅 Jūs išmetėte ir užblokavote {user}", - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "youUnbannedUser": "Jūs atblokavote {user}", - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "dateWithoutYear": "{month}-{day}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateWithYear": "{year}-{month}-{day}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "locationDisabledNotice": "Vietos nustatymo paslaugos yra išjungtos. Kad galėtumėte bendrinti savo buvimo vietą, įjunkite jas.", - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "noMatrixServer": "{server1} nėra Matrix serveris, ar vietoj jo naudoti {server2}?", - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "numUsersTyping": "{count} vartotojai rašo…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "enableMultiAccounts": "(BETA) Įgalinkite kelias paskyras šiame įrenginyje", - "@enableMultiAccounts": {}, - "openInMaps": "Atidaryti žemėlapiuose", - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "sentAPicture": "🖼️ {username} atsiuntė nuotrauką", - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAVideo": "🎥 {username} atsiuntė vaizdo įrašą", - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentCallInformations": "{senderName} išsiuntė skambučio informaciją", - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "setCustomEmotes": "Nustatyti pasirinktinius jaustukus", - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "userLeftTheChat": "🚪 {username} paliko pokalbį", - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "markAsRead": "Žymėti kaip skaitytą", - "@markAsRead": {}, - "pushRules": "Tiesioginių pranešimų taisyklės", - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "unreadChats": "{unreadCount, plural, =1{1 unread chat} other{{unreadCount} neperskaityti pokalbiai}}", - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "addWidget": "Pridėti programėlę", - "@addWidget": {}, - "widgetCustom": "Pasirinktinis", - "@widgetCustom": {}, - "errorAddingWidget": "Pridedant valdiklį įvyko klaida.", - "@errorAddingWidget": {}, - "askSSSSSign": "Kad galėtumėte prijungti kitą asmenį, įveskite savo saugyklos slaptafrazę arba atkūrimo raktą.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "autoplayImages": "Automatiškai leisti animuotus lipdukus ir jaustukus", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "commandHint_markasdm": "Pažymėti kaip tiesioginio pokalbio kambarį", - "@commandHint_markasdm": {}, - "dehydrateTorLong": "TOR naudotojams rekomenduojama eksportuoti sesiją prieš uždarant langą.", - "@dehydrateTorLong": {}, - "dehydrateWarning": "Šio veiksmo negalima atšaukti. Įsitikinkite, kad saugiai saugote atsarginę kopiją.", - "@dehydrateWarning": {}, - "hydrateTorLong": "Ar paskutinį kartą eksportavote savo sesiją naudodami TOR? Greitai ją importuokite ir tęskite pokalbį.", - "@hydrateTorLong": {}, - "commandHint_markasgroup": "Pažymėti kaip grupę", - "@commandHint_markasgroup": {}, - "pleaseEnterRecoveryKeyDescription": "Norėdami atrakinti senas žinutes, įveskite atkūrimo raktą, kuris buvo sukurtas ankstesnės sesijos metu. Atkūrimo raktas NĖRA jūsų slaptažodis.", - "@pleaseEnterRecoveryKeyDescription": {}, - "callingPermissions": "Skambinimo leidimai", - "@callingPermissions": {}, - "storeInAppleKeyChain": "Saugoti Apple raktų grandinėje", - "@storeInAppleKeyChain": {}, - "callingAccount": "Skambinimo paskyra", - "@callingAccount": {}, - "newSpace": "Nauja erdvė", - "@newSpace": {}, - "callingAccountDetails": "Leidžia FluffyChat naudoti vietinę Android rinkiklio programą.", - "@callingAccountDetails": {}, - "appearOnTop": "Rodyti viršuje", - "@appearOnTop": {}, - "enterSpace": "Įeiti į erdvę", - "@enterSpace": {}, - "enterRoom": "Įeiti į kambarį", - "@enterRoom": {}, - "allSpaces": "Visos erdvės", - "@allSpaces": {}, - "user": "Vartotojas", - "@user": {}, - "custom": "Pasirinktinis", - "@custom": {}, - "confirmMatrixId": "Norėdami ištrinti savo paskyrą, patvirtinkite savo Matrix ID.", - "@confirmMatrixId": {}, - "supposedMxid": "Tai turėtų būti {mxid}", - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "dehydrate": "Eksportuoti sesiją ir išvalyti įrenginį", - "@dehydrate": {}, - "dehydrateTor": "TOR Naudotojai: Eksportuoti sesiją", - "@dehydrateTor": {}, - "hydrateTor": "TOR Naudotojai: Importuoti sesijos eksportą", - "@hydrateTor": {}, - "hydrate": "Atkurti iš atsarginės kopijos failo", - "@hydrate": {}, - "pleaseEnterRecoveryKey": "Įveskite savo atkūrimo raktą:", - "@pleaseEnterRecoveryKey": {}, - "recoveryKey": "Atkūrimo raktas", - "@recoveryKey": {}, - "recoveryKeyLost": "Pamestas atkūrimo raktas?", - "@recoveryKeyLost": {}, - "indexedDbErrorLong": "Deja, pagal numatytuosius nustatymus žinučių saugojimas privačiame režime nėra įjungtas.\nPrašome apsilankyti\n - about:config\n - nustatykite dom.indexedDB.privateBrowsing.enabled į true\nPriešingu atveju FluffyChat paleisti neįmanoma.", - "@indexedDbErrorLong": {}, - "countFiles": "{count} failai", - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "storeInSecureStorageDescription": "Atkūrimo raktą laikyti saugioje šio prietaiso saugykloje.", - "@storeInSecureStorageDescription": {}, - "saveKeyManuallyDescription": "Įrašykite šį raktą rankiniu būdu, įjungę sistemos bendrinimo dialogo langą arba iškarpinę.", - "@saveKeyManuallyDescription": {}, - "users": "Vartotojai", - "@users": {}, - "storeSecurlyOnThisDevice": "Saugiai laikyti šiame prietaise", - "@storeSecurlyOnThisDevice": {}, - "unlockOldMessages": "Atrakinti senas žinutes", - "@unlockOldMessages": {}, - "storeInAndroidKeystore": "Saugoti Android raktų saugykloje", - "@storeInAndroidKeystore": {}, - "indexedDbErrorTitle": "Privataus režimo problemos", - "@indexedDbErrorTitle": {}, - "noKeyForThisMessage": "Taip gali atsitikti, jei žinutė buvo išsiųsta prieš prisijungiant prie paskyros šiame prietaise.\n\nTaip pat gali būti, kad siuntėjas užblokavo jūsų prietaisą arba kažkas sutriko su interneto ryšiu.\n\nAr galite perskaityti žinutę kitoje sesijoje? Tada galite perkelti žinutę iš jos! Eikite į Nustatymai > Prietaisai ir įsitikinkite, kad jūsų prietaisai patvirtino vienas kitą. Kai kitą kartą atidarysite kambarį ir abi sesijos bus pirmame plane, raktai bus perduoti automatiškai.\n\nNenorite prarasti raktų atsijungdami arba keisdami įrenginius? Įsitikinkite, kad nustatymuose įjungėte pokalbių atsarginę kopiją.", - "@noKeyForThisMessage": {}, - "foregroundServiceRunning": "Šis pranešimas rodomas, kai veikia pirmojo plano paslauga.", - "@foregroundServiceRunning": {}, - "screenSharingTitle": "ekrano bendrinimas", - "@screenSharingTitle": {}, - "appearOnTopDetails": "Leidžia programėlę rodyti viršuje (nebūtina, jei jau esate nustatę Fluffychat kaip skambinimo paskyrą)", - "@appearOnTopDetails": {}, - "otherCallingPermissions": "Mikrofonas, kamera ir kiti FluffyChat leidimai", - "@otherCallingPermissions": {}, - "whyIsThisMessageEncrypted": "Kodėl ši žinutė neperskaitoma?", - "@whyIsThisMessageEncrypted": {}, - "newGroup": "Nauja grupė", - "@newGroup": {}, - "screenSharingDetail": "Bendrinate savo ekraną per FuffyChat", - "@screenSharingDetail": {}, - "numChats": "{number} pokalbiai", - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "hideUnimportantStateEvents": "Slėpti nesvarbius būsenos įvykius", - "@hideUnimportantStateEvents": {}, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@reportErrorDescription": {}, - "@startFirstChat": {}, - "@setColorTheme": {}, - "@banUserDescription": {}, - "@removeDevicesDescription": {}, - "@tryAgain": {}, - "@unbanUserDescription": {}, - "@messagesStyle": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@encryptThisChat": {}, - "@reopenChat": {}, - "@pushNotificationsNotAvailable": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@signInWithPassword": {}, - "@makeAdminDescription": {}, - "@setChatDescription": {}, - "@importFromZipFile": {}, - "@noOtherDevicesFound": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@fileIsTooBigForServer": {}, - "@readUpToHere": {}, - "@optionalRedactReason": {}, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@redactMessageDescription": {}, - "@invalidInput": {}, - "@doNotShowAgain": {}, - "@report": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@addChatDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@openLinkInBrowser": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@invitePrivateChat": {}, - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "@noChatDescriptionYet": {}, - "@learnMore": {}, - "@notAnImage": {}, - "@chatDescriptionHasBeenChanged": {}, - "@roomUpgradeDescription": {}, - "@pleaseEnterANumber": {}, - "@profileNotFound": {}, - "@jump": {}, - "@sorryThatsNotPossible": {}, - "@shareInviteLink": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@deviceKeys": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@commandHint_hug": {}, - "@replace": {}, - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@noBackupWarning": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@invite": {} -} \ No newline at end of file + "commandHint_leave": "Palikti pokalbių kambarį", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "confirm": "Patvirtinti", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "cancel": "Atšaukti", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "edit": "Redaguoti", + "@edit": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "Atsisiųsti failą", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "about": "Apie", + "@about": { + "type": "text", + "placeholders": {} + }, + "all": "Visi", + "@all": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "fileName": "Failo vardas", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "changePassword": "Keisti slaptažodį", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "close": "Uždaryti", + "@close": { + "type": "text", + "placeholders": {} + }, + "archive": "Archyvas", + "@archive": { + "type": "text", + "placeholders": {} + }, + "skip": "Praleisti", + "@skip": { + "type": "text", + "placeholders": {} + }, + "share": "Bendrinti", + "@share": { + "type": "text", + "placeholders": {} + }, + "showPassword": "Rodyti slaptažodį", + "@showPassword": { + "type": "text", + "placeholders": {} + }, + "time": "Laikas", + "@time": {}, + "settings": "Nustatytmai", + "@settings": { + "type": "text", + "placeholders": {} + }, + "sender": "Siuntėjas", + "@sender": {}, + "yes": "Taip", + "@yes": { + "type": "text", + "placeholders": {} + }, + "you": "Jūs", + "@you": { + "type": "text", + "placeholders": {} + }, + "logout": "Atsijungti", + "@logout": { + "type": "text", + "placeholders": {} + }, + "messages": "Žinutės", + "@messages": { + "type": "text", + "placeholders": {} + }, + "scanQrCode": "Nuskanuokite QR kodą", + "@scanQrCode": {}, + "ok": "OK", + "@ok": { + "type": "text", + "placeholders": {} + }, + "addAccount": "Pridėti paskyrą", + "@addAccount": {}, + "or": "Arba", + "@or": { + "type": "text", + "placeholders": {} + }, + "password": "Slaptažodis", + "@password": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "Slaptažodis pakeistas", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "Įveskite savo slaptažodį", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "Įveskite savo vartotojo vardą", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "reply": "Atsakyti", + "@reply": { + "type": "text", + "placeholders": {} + }, + "blockDevice": "Blokuoti įrenginį", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "blocked": "Užblokuotas", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "Pasirinkite saugų slaptažodį", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "Ištrinti žinutę", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "device": "Įrenginys", + "@device": { + "type": "text", + "placeholders": {} + }, + "deviceId": "Įrenginio ID", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "devices": "Įrenginiai", + "@devices": { + "type": "text", + "placeholders": {} + }, + "homeserver": "Namų serveris", + "@homeserver": {}, + "enterYourHomeserver": "Įveskite namų serverį", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "everythingReady": "Viskas paruošta!", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "fontSize": "Šrifto dydis", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "clearArchive": "Išvalyti archyvą", + "@clearArchive": {}, + "create": "Sukurti", + "@create": { + "type": "text", + "placeholders": {} + }, + "connect": "Prisijungti", + "@connect": { + "type": "text", + "placeholders": {} + }, + "people": "Žmonės", + "@people": { + "type": "text", + "placeholders": {} + }, + "moderator": "Moderatorius", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "muteChat": "Nutildyti pokalbį", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "newChat": "Naujas pokalbis", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "none": "Nė vienas", + "@none": { + "type": "text", + "placeholders": {} + }, + "noPermission": "Nėra leidimo", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "Nerasta kambarių…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "notifications": "Pranešimai", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "notificationsEnabledForThisAccount": "Pranešimai aktyvuoti šitai paskyrai", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "obtainingLocation": "Gaunama vieta…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "offensive": "Agresyvus", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "offline": "Neprisijungta", + "@offline": { + "type": "text", + "placeholders": {} + }, + "online": "Prisijungta", + "@online": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "Oi! Deja, nustatant tiesioginius pranešimus įvyko klaida.", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "Oi, kažkas nutiko ne taip…", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "Atidarykite programėlę, kad perskaityti žinutes", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "link": "Nuoroda", + "@link": {}, + "participant": "Dalyvis", + "@participant": { + "type": "text", + "placeholders": {} + }, + "passphraseOrKey": "Slapta frazė arba atkūrimo raktas", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "Slaptažodis užmirštas", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "passwordRecovery": "Slaptažodžio atkūrimas", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "pickImage": "Pasirinkite paveiksliuką", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "pin": "Prisegti", + "@pin": { + "type": "text", + "placeholders": {} + }, + "pleaseChoose": "Prašome pasirinkti", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "pleaseChooseAPasscode": "Pasirinkite slaptą kodą", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pleaseClickOnLink": "Paspauskite nuorodą el. pašte ir tęskite toliau.", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "Įveskite 4 skaitmenis arba palikite tuščią, jei norite išjungti programėlės užraktą.", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "Įveskite savo PIN kodą", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "pleaseFollowInstructionsOnWeb": "Vadovaukitės svetainėje pateiktais nurodymais ir bakstelėkite Toliau.", + "@pleaseFollowInstructionsOnWeb": { + "type": "text", + "placeholders": {} + }, + "privacy": "Privatumas", + "@privacy": { + "type": "text", + "placeholders": {} + }, + "publicRooms": "Vieši kambariai", + "@publicRooms": { + "type": "text", + "placeholders": {} + }, + "reason": "Priežastis", + "@reason": { + "type": "text", + "placeholders": {} + }, + "recording": "Įrašymas", + "@recording": { + "type": "text", + "placeholders": {} + }, + "redactMessage": "Pašalinti žinutę", + "@redactMessage": { + "type": "text", + "placeholders": {} + }, + "register": "Registruotis", + "@register": { + "type": "text", + "placeholders": {} + }, + "reject": "Atmesti", + "@reject": { + "type": "text", + "placeholders": {} + }, + "rejoin": "Vėl prisijungti", + "@rejoin": { + "type": "text", + "placeholders": {} + }, + "remove": "Pašalinti", + "@remove": { + "type": "text", + "placeholders": {} + }, + "removeAllOtherDevices": "Pašalinti visus kitus įrenginius", + "@removeAllOtherDevices": { + "type": "text", + "placeholders": {} + }, + "removeDevice": "Pašalinti įrenginį", + "@removeDevice": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "Pašalinti savo avatarą", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "replaceRoomWithNewerVersion": "Pakeisti kambarį naujesne versija", + "@replaceRoomWithNewerVersion": { + "type": "text", + "placeholders": {} + }, + "requestPermission": "Prašyti leidimo", + "@requestPermission": { + "type": "text", + "placeholders": {} + }, + "roomHasBeenUpgraded": "Kambarys buvo atnaujintas", + "@roomHasBeenUpgraded": { + "type": "text", + "placeholders": {} + }, + "roomVersion": "Kambario versija", + "@roomVersion": { + "type": "text", + "placeholders": {} + }, + "search": "Ieškoti", + "@search": { + "type": "text", + "placeholders": {} + }, + "accept": "Sutinku", + "@accept": { + "type": "text", + "placeholders": {} + }, + "repeatPassword": "Pakartokite slaptažodį", + "@repeatPassword": {}, + "addEmail": "Pridėti el. paštą", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "admin": "Administratorius", + "@admin": { + "type": "text", + "placeholders": {} + }, + "alias": "slapyvardis", + "@alias": { + "type": "text", + "placeholders": {} + }, + "allChats": "Visi pokalbiai", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "anyoneCanJoin": "Bet kas gali prisijungti", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "Ar esate tikri?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "areYouSureYouWantToLogout": "Ar tikrai norite atsijungti?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "changeTheHomeserver": "Pakeisti namų serverį", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "Keisti savo stilių", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "Keisti grupės pavadinimą", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "changeYourAvatar": "Keisti savo avatarą", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "chat": "Pokalbis", + "@chat": { + "type": "text", + "placeholders": {} + }, + "chatDetails": "Pokalbio detalės", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chats": "Pokalbiai", + "@chats": { + "type": "text", + "placeholders": {} + }, + "commandHint_ban": "Užblokuoti vartotoją šiame kambaryje", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_clearcache": "Išvalyti laikiną talpyklą", + "@commandHint_clearcache": { + "type": "text", + "description": "Usage hint for the command /clearcache" + }, + "commandHint_discardsession": "Atmesti sesiją", + "@commandHint_discardsession": { + "type": "text", + "description": "Usage hint for the command /discardsession" + }, + "commandHint_html": "Siųsti tekstą HTML formatu", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_invite": "Pakviesti vartotoją į šitą kambarį", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "commandHint_join": "Prisijungti prie nurodyto kambario", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_kick": "Pašalinti vartotoja iš šito kambario", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_myroomnick": "Nustatyti savo rodomą vardą šiame kambaryje", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "commandHint_plain": "Siųsti neformatuotą tekstą", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_send": "Siųsti tekstą", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "commandHint_unban": "Atblokuoti vartotoją šiame kambaryje", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "commandInvalid": "Neteisinga komanda", + "@commandInvalid": { + "type": "text" + }, + "configureChat": "Konfigūruoti pokalbį", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "Nukopijuota į iškarpinę", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "copy": "Kopijuoti", + "@copy": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "Koipjuoti į iškarpinę", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "currentlyActive": "Šiuo metu aktyvus", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "Tamsi", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "delete": "Ištrinti", + "@delete": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "Panaikinti paskyra", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "directChats": "Tiesioginiai pokalbiai", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "encrypted": "Užšifruotas", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "encryptionNotEnabled": "Šifravimas aktyvuotas", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "enterAnEmailAddress": "Įveskite el. pašto adresą", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "extremeOffensive": "Itin įžeidžiantis", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "forward": "Toliau", + "@forward": { + "type": "text", + "placeholders": {} + }, + "fromJoining": "Nuo prisijungimo", + "@fromJoining": { + "type": "text", + "placeholders": {} + }, + "fromTheInvitation": "Nuo pakvietimo", + "@fromTheInvitation": { + "type": "text", + "placeholders": {} + }, + "goToTheNewRoom": "Eiti į naują kambarį", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "group": "Grupė", + "@group": { + "type": "text", + "placeholders": {} + }, + "groupIsPublic": "Grupė yra vieša", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "groups": "Grupės", + "@groups": { + "type": "text", + "placeholders": {} + }, + "guestsAreForbidden": "Svečiams draudžiama", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "Svečiai gali prisijungti", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "help": "Pagalba", + "@help": { + "type": "text", + "placeholders": {} + }, + "hideRedactedEvents": "Slėpti pašalintus įvykius", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "Slėpti nežinomus įvykius", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "identity": "Tapatybė", + "@identity": { + "type": "text", + "placeholders": {} + }, + "ignore": "Ignoruoti", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "Ignoruoti vartotojai", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "leave": "Palikti", + "@leave": { + "type": "text", + "placeholders": {} + }, + "memberChanges": "Narių pokyčiai", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "mention": "Paminėti", + "@mention": { + "type": "text", + "placeholders": {} + }, + "encryption": "Šifravimas", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "Aktyvuoti šifravimą", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "Redaguoti blokuotus serverius", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "login": "Prisijungti", + "@login": { + "type": "text", + "placeholders": {} + }, + "sendOnEnter": "Išsiųsti paspaudus Enter", + "@sendOnEnter": {}, + "banFromChat": "Užblokuoti iš pokalbio", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "banned": "Užblokuotas", + "@banned": { + "type": "text", + "placeholders": {} + }, + "changeDeviceName": "Pakeisti įrenginio vardą", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "yourChatBackupHasBeenSetUp": "Jūsų pokalbio atsarginė kopija buvo nustatyta.", + "@yourChatBackupHasBeenSetUp": {}, + "chatBackup": "Pokalbio atsargine kopija", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "commandHint_me": "Apibūdinkite save", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "displaynameHasBeenChanged": "Rodomas vardas buvo pakeistas", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "Redaguoti rodomą vardą", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "Redaguoti kambario pseudonimus", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "Redaguoti kambario avatarą", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "howOffensiveIsThisContent": "Kiek įžeižiantis šis turinys?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "id": "ID", + "@id": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "Aš paspaudžiau nuorodą", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "incorrectPassphraseOrKey": "Neteisinga slaptafrazė arba atkūrimo raktas", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "Neįžeidžiantis", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "Pakviesti kontaktą", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "invited": "Pakviestas", + "@invited": { + "type": "text", + "placeholders": {} + }, + "invitedUsersOnly": "Tik pakviesti vartotojai", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "isTyping": "rašo…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "joinRoom": "Prisijungti prie kambario", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "kickFromChat": "Išmesti iš pokalbio", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "leftTheChat": "Paliko pokalbį", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "license": "Licencija", + "@license": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "Šviesi", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "loadingPleaseWait": "Kraunama… Prašome palaukti.", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "loadMore": "Rodyti daugiau…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "💬 Nauja žinutė FluffyChat'e", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "newVerificationRequest": "Nauja patvirtinimo užklausa!", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "next": "Toliau", + "@next": { + "type": "text", + "placeholders": {} + }, + "no": "Ne", + "@no": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "Nėra ryšio su serveriu", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "setInvitationLink": "Nustatyti pakvietimo nuorodą", + "@setInvitationLink": { + "type": "text", + "placeholders": {} + }, + "singlesignon": "Vienkartinis prisijungimas", + "@singlesignon": { + "type": "text", + "placeholders": {} + }, + "sourceCode": "Programinis kodas", + "@sourceCode": { + "type": "text", + "placeholders": {} + }, + "spaceIsPublic": "Erdvė yra vieša", + "@spaceIsPublic": { + "type": "text", + "placeholders": {} + }, + "spaceName": "Erdvės pavadinimas", + "@spaceName": { + "type": "text", + "placeholders": {} + }, + "status": "Būsena", + "@status": { + "type": "text", + "placeholders": {} + }, + "statusExampleMessage": "Kaip sekasi šiandien?", + "@statusExampleMessage": { + "type": "text", + "placeholders": {} + }, + "submit": "Pateikti", + "@submit": { + "type": "text", + "placeholders": {} + }, + "synchronizingPleaseWait": "Sinchronizuojama… Prašome palaukti.", + "@synchronizingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "transferFromAnotherDevice": "Perkėlimas iš kito įrenginio", + "@transferFromAnotherDevice": { + "type": "text", + "placeholders": {} + }, + "verify": "Patvirtinti", + "@verify": { + "type": "text", + "placeholders": {} + }, + "verifyStart": "Pradėti patvirtinimą", + "@verifyStart": { + "type": "text", + "placeholders": {} + }, + "verifySuccess": "Jūs sėkmingai patvirtinote!", + "@verifySuccess": { + "type": "text", + "placeholders": {} + }, + "verifyTitle": "Patvirtinama kita paskyra", + "@verifyTitle": { + "type": "text", + "placeholders": {} + }, + "visibilityOfTheChatHistory": "Pokalbių istorijos matomumas", + "@visibilityOfTheChatHistory": { + "type": "text", + "placeholders": {} + }, + "visibleForAllParticipants": "Matoma visiems dalyviams", + "@visibleForAllParticipants": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerAcceptRequest": "Laukiama, kol dalyvis priims užklausą…", + "@waitingPartnerAcceptRequest": { + "type": "text", + "placeholders": {} + }, + "writeAMessage": "Rašyti žinutę…", + "@writeAMessage": { + "type": "text", + "placeholders": {} + }, + "youAreNoLongerParticipatingInThisChat": "Jūs nebedalyvaujate šiame pokalbyje", + "@youAreNoLongerParticipatingInThisChat": { + "type": "text", + "placeholders": {} + }, + "youHaveBeenBannedFromThisChat": "Jums buvo uždrausta dalyvauti šiame pokalbyje", + "@youHaveBeenBannedFromThisChat": { + "type": "text", + "placeholders": {} + }, + "messageInfo": "Žinutės informacija", + "@messageInfo": {}, + "removeFromSpace": "Pašalinti iš erdvės", + "@removeFromSpace": {}, + "security": "Apsauga", + "@security": { + "type": "text", + "placeholders": {} + }, + "sendAsText": "Siųsti kaip tekstą", + "@sendAsText": { + "type": "text" + }, + "sendAudio": "Siųsti garso įrašą", + "@sendAudio": { + "type": "text", + "placeholders": {} + }, + "sendImage": "Siųsti paveiksliuką", + "@sendImage": { + "type": "text", + "placeholders": {} + }, + "sendFile": "Sųsti bylą", + "@sendFile": { + "type": "text", + "placeholders": {} + }, + "sendMessages": "Siųsti žinutes", + "@sendMessages": { + "type": "text", + "placeholders": {} + }, + "sendOriginal": "Siųsti originalą", + "@sendOriginal": { + "type": "text", + "placeholders": {} + }, + "sendVideo": "Siųsti video", + "@sendVideo": { + "type": "text", + "placeholders": {} + }, + "separateChatTypes": "Atskirti tiesioginius pokalbius ir grupes", + "@separateChatTypes": { + "type": "text", + "placeholders": {} + }, + "setAsCanonicalAlias": "Nustatyti kaip pagrindinį slapyvardį", + "@setAsCanonicalAlias": { + "type": "text", + "placeholders": {} + }, + "setPermissionsLevel": "Nustatyti leidimų lygį", + "@setPermissionsLevel": { + "type": "text", + "placeholders": {} + }, + "setStatus": "Nustatyti būseną", + "@setStatus": { + "type": "text", + "placeholders": {} + }, + "shareLocation": "Bendrinti vietą", + "@shareLocation": { + "type": "text", + "placeholders": {} + }, + "systemTheme": "Sistema", + "@systemTheme": { + "type": "text", + "placeholders": {} + }, + "unavailable": "Nepasiekiamas", + "@unavailable": { + "type": "text", + "placeholders": {} + }, + "unblockDevice": "Atblokuoti įrenginį", + "@unblockDevice": { + "type": "text", + "placeholders": {} + }, + "unknownEncryptionAlgorithm": "Nežinomas šifravimo algoritmas", + "@unknownEncryptionAlgorithm": { + "type": "text", + "placeholders": {} + }, + "unmuteChat": "Įjungti pokalbio garsą", + "@unmuteChat": { + "type": "text", + "placeholders": {} + }, + "unpin": "Atsegti", + "@unpin": { + "type": "text", + "placeholders": {} + }, + "username": "Vartotojo vardas", + "@username": { + "type": "text", + "placeholders": {} + }, + "unverified": "Nepatvirtinta", + "@unverified": {}, + "verified": "Patvirtinta", + "@verified": { + "type": "text", + "placeholders": {} + }, + "videoCall": "Vaizdo skambutis", + "@videoCall": { + "type": "text", + "placeholders": {} + }, + "yourPublicKey": "Jūsų viešasis raktas", + "@yourPublicKey": { + "type": "text", + "placeholders": {} + }, + "addToSpaceDescription": "Pasirinkite erdvę, kad prie jos pridėtumėte šį pokalbį.", + "@addToSpaceDescription": {}, + "start": "Pradžia", + "@start": {}, + "account": "Paskyra", + "@account": { + "type": "text", + "placeholders": {} + }, + "addToSpace": "Pridėti į erdvę", + "@addToSpace": {}, + "appLock": "Programos užraktas", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "Ar svečiams leidžiama prisijungti", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "botMessages": "Botų žinutės", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "channelCorruptedDecryptError": "Šifravimas buvo sugadintas", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "chatHasBeenAddedToThisSpace": "Pokalbis buvo pridėtas prie šios erdvės", + "@chatHasBeenAddedToThisSpace": {}, + "compareEmojiMatch": "Palyginkite jaustukus", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "Palyginkite skaičius", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "Kontaktas buvo pakviestas į grupę", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "Apie turinį pranešta serverio administratoriams", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "createNewSpace": "Nauja erdvė", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "deactivateAccountWarning": "Tai deaktyvuos jūsų vartotojo paskyrą. Tai negali būti atšaukta! Ar jūs tuo tikri?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "Numatytasis teisių lygis", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "enableEncryptionWarning": "Šifravimo nebegalėsite išjungti. Ar jūs tuo tikri?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "send": "Siųsti", + "@send": { + "type": "text", + "placeholders": {} + }, + "sendAMessage": "Siųsti žinutę", + "@sendAMessage": { + "type": "text", + "placeholders": {} + }, + "toggleUnread": "Pažymėti kaip skaitytą/neskaitytą", + "@toggleUnread": { + "type": "text", + "placeholders": {} + }, + "tooManyRequestsWarning": "Per daug užklausų. Pabandykite dar kartą vėliau!", + "@tooManyRequestsWarning": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerEmoji": "Laukiama, kol dalyvis priims jaustukus…", + "@waitingPartnerEmoji": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerNumbers": "Laukiama, kol dalyvis priims skaičius…", + "@waitingPartnerNumbers": { + "type": "text", + "placeholders": {} + }, + "wallpaper": "Užsklanda", + "@wallpaper": { + "type": "text", + "placeholders": {} + }, + "warning": "Įspėjimas!", + "@warning": { + "type": "text", + "placeholders": {} + }, + "weSentYouAnEmail": "Išsiuntėme jums el. laišką", + "@weSentYouAnEmail": { + "type": "text", + "placeholders": {} + }, + "whoCanPerformWhichAction": "Kas gali atlikti kokį veiksmą", + "@whoCanPerformWhichAction": { + "type": "text", + "placeholders": {} + }, + "whoIsAllowedToJoinThisGroup": "Kam leidžiama prisijungti prie šios grupės", + "@whoIsAllowedToJoinThisGroup": { + "type": "text", + "placeholders": {} + }, + "whyDoYouWantToReportThis": "Kodėl norite apie tai pranešti?", + "@whyDoYouWantToReportThis": { + "type": "text", + "placeholders": {} + }, + "wipeChatBackup": "Ištrinti atsarginę pokalbių kopiją, kad sukurti naują atkūrimo raktą?", + "@wipeChatBackup": { + "type": "text", + "placeholders": {} + }, + "withTheseAddressesRecoveryDescription": "Naudodami šiuos adresus galite atkurti savo slaptažodį.", + "@withTheseAddressesRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "messageType": "Žinutės tipas", + "@messageType": {}, + "openGallery": "Atverti galeriją", + "@openGallery": {}, + "unknownDevice": "Nežinomas įrenginys", + "@unknownDevice": { + "type": "text", + "placeholders": {} + }, + "voiceMessage": "Balso žinutė", + "@voiceMessage": { + "type": "text", + "placeholders": {} + }, + "title": "FluffyChat", + "@title": { + "description": "Title for the application", + "type": "text", + "placeholders": {} + }, + "visibleForEveryone": "Matoma visiems", + "@visibleForEveryone": { + "type": "text", + "placeholders": {} + }, + "tryToSendAgain": "Pabandykite išsiųsti dar kartą", + "@tryToSendAgain": { + "type": "text", + "placeholders": {} + }, + "locationPermissionDeniedNotice": "Vietos leidimas atmestas. Suteikite leidimą kad galėtumėte bendrinti savo vietą.", + "@locationPermissionDeniedNotice": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "Atminkite, kad norint naudoti end-to-end šifravimą, reikalingas Pantalaimon.", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "Šifravimą galite suaktyvinti tik tada, kai kambarys nebebus viešai pasiekiamas.", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "noEmotesFound": "Nerasta jaustukų. 😕", + "@noEmotesFound": { + "type": "text", + "placeholders": {} + }, + "noGoogleServicesWarning": "Atrodo, kad jūsų telefone nėra Google Services. Tai geras sprendimas jūsų privatumui! Norėdami gauti tiesioginius pranešimus FluffyChat, rekomenduojame naudoti https://microg.org/ arba https://unifiedpush.org/.", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "Dar nepridėjote slaptažodžio atkūrimo būdo.", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "oneClientLoggedOut": "Vienas iš jūsų klientų atsijungė", + "@oneClientLoggedOut": {}, + "onlineKeyBackupEnabled": "Internetinė atsarginė raktų kopija įjungta", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "openCamera": "Atidarykite kamerą", + "@openCamera": { + "type": "text", + "placeholders": {} + }, + "openVideoCamera": "Atidarykite kamerą vaizdo įrašui", + "@openVideoCamera": { + "type": "text", + "placeholders": {} + }, + "editBundlesForAccount": "Redaguoti šios paskyros paketus", + "@editBundlesForAccount": {}, + "serverRequiresEmail": "Šis serveris turi patvirtinti jūsų el. pašto adresą registracijai.", + "@serverRequiresEmail": {}, + "addToBundle": "Pridėti prie paketų", + "@addToBundle": {}, + "removeFromBundle": "Pašalinkite iš šio paketo", + "@removeFromBundle": {}, + "bundleName": "Paketo vardas", + "@bundleName": {}, + "play": "Groti {fileName}", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "redactedAnEvent": "{username} pašalino įvykį", + "@redactedAnEvent": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "rejectedTheInvitation": "{username} atmetė kvietimą", + "@rejectedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removedBy": "Pašalino vartotojas {username}", + "@removedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "unbanFromChat": "Atblokuoti pokalbyje", + "@unbanFromChat": { + "type": "text", + "placeholders": {} + }, + "renderRichContent": "Atvaizduoti turtingą žinutės turinį", + "@renderRichContent": { + "type": "text", + "placeholders": {} + }, + "reportMessage": "Pranešti apie žinutę", + "@reportMessage": { + "type": "text", + "placeholders": {} + }, + "saveFile": "Išsaugoti failą", + "@saveFile": { + "type": "text", + "placeholders": {} + }, + "seenByUser": "Matė {username}", + "@seenByUser": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sendSticker": "Siųsti lipduką", + "@sendSticker": { + "type": "text", + "placeholders": {} + }, + "sentAFile": "📁 {username} atsiuntė failą", + "@sentAFile": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAnAudio": "🎤 {username} atsiuntė garso įrašą", + "@sentAnAudio": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentASticker": "😊 {username} atsiuntė lipduką", + "@sentASticker": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sharedTheLocation": "{username} bendrino savo vietą", + "@sharedTheLocation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "startedACall": "{senderName} pradėjo skambutį", + "@startedACall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "theyDontMatch": "Jie nesutampa", + "@theyDontMatch": { + "type": "text", + "placeholders": {} + }, + "theyMatch": "Jie sutampa", + "@theyMatch": { + "type": "text", + "placeholders": {} + }, + "unbannedUser": "{username} atblokavo {targetName}", + "@unbannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "unknownEvent": "Nežinomas įvykis '{type}'", + "@unknownEvent": { + "type": "text", + "placeholders": { + "type": {} + } + }, + "userAndOthersAreTyping": "{username} ir dar {count} kiti rašo…", + "@userAndOthersAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "count": {} + } + }, + "userAndUserAreTyping": "{username} ir {username2} rašo…", + "@userAndUserAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "username2": {} + } + }, + "userIsTyping": "{username} rašo…", + "@userIsTyping": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "userSentUnknownEvent": "{username} išsiuntė {type} įvykį", + "@userSentUnknownEvent": { + "type": "text", + "placeholders": { + "username": {}, + "type": {} + } + }, + "publish": "Paskelbti", + "@publish": {}, + "openChat": "Atverti pokalbį", + "@openChat": {}, + "reportUser": "Pranešti apie vartotoją", + "@reportUser": {}, + "dismiss": "Atsisakyti", + "@dismiss": {}, + "reactedWith": "{sender} sureagavo su {reaction}", + "@reactedWith": { + "type": "text", + "placeholders": { + "sender": {}, + "reaction": {} + } + }, + "unsupportedAndroidVersion": "Nepalaikoma Android versija", + "@unsupportedAndroidVersion": {}, + "emailOrUsername": "El. paštas arba vartotojo vardas", + "@emailOrUsername": {}, + "widgetVideo": "Video", + "@widgetVideo": {}, + "widgetNameError": "Pateikite rodomą vardą.", + "@widgetNameError": {}, + "acceptedTheInvitation": "👍 {username} priėmė kvietimą", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "activatedEndToEndEncryption": "🔐 {username} aktyvavo visapusį šifravimą", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "answeredTheCall": "{senderName} atsiliepė į skambutį", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "askVerificationRequest": "Priimti šią patvirtinimo užklausą iš {username}?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "badServerLoginTypesException": "Namų serveris palaiko šiuos prisijungimo tipus:\n{serverVersions}\nTačiau ši programa palaiko tik:\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "badServerVersionsException": "Namų serveris palaiko spec. versijas:\n{serverVersions}\nTačiau ši programa palaiko tik {supportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "bannedUser": "{username} užblokavo {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "changedTheHistoryVisibility": "{username} pakeitė istorijos matomumą", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibilityTo": "{username} pakeitė istorijos matomumą į: {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "chatBackupDescription": "Jūsų senos žinutės yra apsaugotos atkūrimo raktu. Pasirūpinkite, kad jo neprarastumėte.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "commandHint_create": "Sukurti tuščią grupinį pokalbį\nNaudokite --no-encryption kad išjungti šifravimą", + "@commandHint_create": { + "type": "text", + "description": "Usage hint for the command /create" + }, + "commandHint_dm": "Pradėti tiesioginį pokalbį\nNaudokite --no-encryption kad išjungti šifravimą", + "@commandHint_dm": { + "type": "text", + "description": "Usage hint for the command /dm" + }, + "commandHint_myroomavatar": "Nustatyti savo nuotrauką šiame kambaryje (su mxc-uri)", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_op": "Nustatyti naudotojo galios lygį (numatytasis: 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_react": "Siųsti atsakymą kaip reakciją", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "commandMissing": "{command} nėra komanda.", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "containsDisplayName": "Turi rodomą vardą", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "containsUserName": "Turi vartotojo vardą", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "Nepavyko iššifruoti pranešimo: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "countParticipants": "{count} dalyviai", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "createdTheChat": "💬 {username} sukūrė pokalbį", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "emptyChat": "Tuščias pokalbis", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "Jaustukas jau egzistuoja!", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "emoteInvalid": "Neteisingas jaustuko trumpasis kodas!", + "@emoteInvalid": { + "type": "text", + "placeholders": {} + }, + "emotePacks": "Jaustukų paketai kambariui", + "@emotePacks": { + "type": "text", + "placeholders": {} + }, + "emoteSettings": "Jaustukų nustatymai", + "@emoteSettings": { + "type": "text", + "placeholders": {} + }, + "emoteShortcode": "Jaustuko trumpasis kodas", + "@emoteShortcode": { + "type": "text", + "placeholders": {} + }, + "emoteWarnNeedToPick": "Turite pasirinkti jaustuko trumpąjį kodą ir paveiksliuką!", + "@emoteWarnNeedToPick": { + "type": "text", + "placeholders": {} + }, + "enableEmotesGlobally": "Įgalinti jaustukų paketą visur", + "@enableEmotesGlobally": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "{senderName} baigė skambutį", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "errorObtainingLocation": "Klaida nustatant vietą: {error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "groupWith": "Grupė su {displayname}", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "hasWithdrawnTheInvitationFor": "{username} atšaukė {targetName} kvietimą", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "inviteForMe": "Pakvietimas man", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "Pakviesti kontaktą į {groupName}", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "invitedUser": "📩 {username} pakvietė {targetName}", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "inviteText": "{username} pakvietė jus prisijungti prie FluffyChat. \n1. Įdiekite FluffyChat: https://fluffychat.im \n2. Prisiregistruokite arba prisijunkite \n3. Atidarykite pakvietimo nuorodą: {link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "joinedTheChat": "👋 {username} prisijungė prie pokalbio", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "kicked": "👞 {username} išmetė {targetName}", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickedAndBanned": "🙅 {username} išmetė ir užblokavo {targetName}", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "lastActiveAgo": "Paskutinis aktyvumas: {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "loadCountMoreParticipants": "Įkelti dar {count} dalyvius", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "logInTo": "Prisijungti prie {homeserver}", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "toggleFavorite": "Perjungti parankinius", + "@toggleFavorite": { + "type": "text", + "placeholders": {} + }, + "toggleMuted": "Perjungti nutildytą", + "@toggleMuted": { + "type": "text", + "placeholders": {} + }, + "cantOpenUri": "Nepavyksta atidaryti URI {uri}", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "changedTheChatAvatar": "{username} pakeitė pokalbio avatarą", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatDescriptionTo": "{username} pakeitė pokalbio aprašymą į: '{description}'", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "changedTheChatNameTo": "{username} pakeitė pokalbio pavadinimą į: '{chatname}'", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changedTheChatPermissions": "{username} pakeitė pokalbių leidimus", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "{username} pakeitė rodomą vardą į: '{displayname}'", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRules": "{username} pakeitė svečio prieigos taisykles", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheGuestAccessRulesTo": "{username} pakeitė svečio prieigos taisykles į: {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRules": "{username} pakeitė prisijungimo taisykles", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheJoinRulesTo": "{username} pakeitė prisijungimo taisykles į: {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheProfileAvatar": "{username} pakeitė savo avatarą", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "{username} pakeitė kambario pseudonimus", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomInvitationLink": "{username} pakeitė pakvietimo nuorodą", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "videoWithSize": "Vaizdo įrašas ({size})", + "@videoWithSize": { + "type": "text", + "placeholders": { + "size": {} + } + }, + "pinMessage": "Prisegti prie kambario", + "@pinMessage": {}, + "confirmEventUnpin": "Ar tikrai norite visam laikui atsegti įvykį?", + "@confirmEventUnpin": {}, + "emojis": "Jaustukai", + "@emojis": {}, + "placeCall": "Skambinti", + "@placeCall": {}, + "voiceCall": "Balso skambutis", + "@voiceCall": {}, + "unsupportedAndroidVersionLong": "Šiai funkcijai reikalinga naujesnė Android versija. Patikrinkite, ar nėra naujinimų arba Lineage OS palaikymo.", + "@unsupportedAndroidVersionLong": {}, + "videoCallsBetaWarning": "Atminkite, kad vaizdo skambučiai šiuo metu yra beta versijos. Jie gali neveikti taip kaip tikėtasi, arba iš viso neveikti visose platformose.", + "@videoCallsBetaWarning": {}, + "experimentalVideoCalls": "Eksperimentiniai vaizdo skambučiai", + "@experimentalVideoCalls": {}, + "switchToAccount": "Perjungti paskyrą į {number}", + "@switchToAccount": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "nextAccount": "Kita paskyra", + "@nextAccount": {}, + "previousAccount": "Ankstesnė paskyra", + "@previousAccount": {}, + "widgetEtherpad": "Teksto pastaba", + "@widgetEtherpad": {}, + "widgetJitsi": "Jitsi Meet", + "@widgetJitsi": {}, + "widgetName": "Vardas", + "@widgetName": {}, + "widgetUrlError": "Netinkamas URL.", + "@widgetUrlError": {}, + "youRejectedTheInvitation": "Jūs atmetėte kvietimą", + "@youRejectedTheInvitation": {}, + "youJoinedTheChat": "Jūs prisijungėte prie pokalbio", + "@youJoinedTheChat": {}, + "youAcceptedTheInvitation": "👍 Jūs priėmėte kvietimą", + "@youAcceptedTheInvitation": {}, + "youBannedUser": "Jūs užblokavote {user}", + "@youBannedUser": { + "placeholders": { + "user": {} + } + }, + "youHaveWithdrawnTheInvitationFor": "Jūs atšaukėte kvietimą {user}", + "@youHaveWithdrawnTheInvitationFor": { + "placeholders": { + "user": {} + } + }, + "youInvitedBy": "📩 Jus pakvietė {user}", + "@youInvitedBy": { + "placeholders": { + "user": {} + } + }, + "youKicked": "👞 Jūs išmetėte {user}", + "@youKicked": { + "placeholders": { + "user": {} + } + }, + "youInvitedUser": "📩 Pakvietėte {user}", + "@youInvitedUser": { + "placeholders": { + "user": {} + } + }, + "youKickedAndBanned": "🙅 Jūs išmetėte ir užblokavote {user}", + "@youKickedAndBanned": { + "placeholders": { + "user": {} + } + }, + "youUnbannedUser": "Jūs atblokavote {user}", + "@youUnbannedUser": { + "placeholders": { + "user": {} + } + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "dateWithoutYear": "{month}-{day}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "dateWithYear": "{year}-{month}-{day}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "locationDisabledNotice": "Vietos nustatymo paslaugos yra išjungtos. Kad galėtumėte bendrinti savo buvimo vietą, įjunkite jas.", + "@locationDisabledNotice": { + "type": "text", + "placeholders": {} + }, + "noMatrixServer": "{server1} nėra Matrix serveris, ar vietoj jo naudoti {server2}?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "numUsersTyping": "{count} vartotojai rašo…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "enableMultiAccounts": "(BETA) Įgalinkite kelias paskyras šiame įrenginyje", + "@enableMultiAccounts": {}, + "openInMaps": "Atidaryti žemėlapiuose", + "@openInMaps": { + "type": "text", + "placeholders": {} + }, + "sentAPicture": "🖼️ {username} atsiuntė nuotrauką", + "@sentAPicture": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAVideo": "🎥 {username} atsiuntė vaizdo įrašą", + "@sentAVideo": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentCallInformations": "{senderName} išsiuntė skambučio informaciją", + "@sentCallInformations": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "setCustomEmotes": "Nustatyti pasirinktinius jaustukus", + "@setCustomEmotes": { + "type": "text", + "placeholders": {} + }, + "userLeftTheChat": "🚪 {username} paliko pokalbį", + "@userLeftTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "markAsRead": "Žymėti kaip skaitytą", + "@markAsRead": {}, + "pushRules": "Tiesioginių pranešimų taisyklės", + "@pushRules": { + "type": "text", + "placeholders": {} + }, + "unreadChats": "{unreadCount, plural, =1{1 unread chat} other{{unreadCount} neperskaityti pokalbiai}}", + "@unreadChats": { + "type": "text", + "placeholders": { + "unreadCount": {} + } + }, + "addWidget": "Pridėti programėlę", + "@addWidget": {}, + "widgetCustom": "Pasirinktinis", + "@widgetCustom": {}, + "errorAddingWidget": "Pridedant valdiklį įvyko klaida.", + "@errorAddingWidget": {}, + "askSSSSSign": "Kad galėtumėte prijungti kitą asmenį, įveskite savo saugyklos slaptafrazę arba atkūrimo raktą.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "autoplayImages": "Automatiškai leisti animuotus lipdukus ir jaustukus", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "commandHint_markasdm": "Pažymėti kaip tiesioginio pokalbio kambarį", + "@commandHint_markasdm": {}, + "dehydrateTorLong": "TOR naudotojams rekomenduojama eksportuoti sesiją prieš uždarant langą.", + "@dehydrateTorLong": {}, + "dehydrateWarning": "Šio veiksmo negalima atšaukti. Įsitikinkite, kad saugiai saugote atsarginę kopiją.", + "@dehydrateWarning": {}, + "hydrateTorLong": "Ar paskutinį kartą eksportavote savo sesiją naudodami TOR? Greitai ją importuokite ir tęskite pokalbį.", + "@hydrateTorLong": {}, + "commandHint_markasgroup": "Pažymėti kaip grupę", + "@commandHint_markasgroup": {}, + "pleaseEnterRecoveryKeyDescription": "Norėdami atrakinti senas žinutes, įveskite atkūrimo raktą, kuris buvo sukurtas ankstesnės sesijos metu. Atkūrimo raktas NĖRA jūsų slaptažodis.", + "@pleaseEnterRecoveryKeyDescription": {}, + "callingPermissions": "Skambinimo leidimai", + "@callingPermissions": {}, + "storeInAppleKeyChain": "Saugoti Apple raktų grandinėje", + "@storeInAppleKeyChain": {}, + "callingAccount": "Skambinimo paskyra", + "@callingAccount": {}, + "newSpace": "Nauja erdvė", + "@newSpace": {}, + "callingAccountDetails": "Leidžia FluffyChat naudoti vietinę Android rinkiklio programą.", + "@callingAccountDetails": {}, + "appearOnTop": "Rodyti viršuje", + "@appearOnTop": {}, + "enterSpace": "Įeiti į erdvę", + "@enterSpace": {}, + "enterRoom": "Įeiti į kambarį", + "@enterRoom": {}, + "allSpaces": "Visos erdvės", + "@allSpaces": {}, + "user": "Vartotojas", + "@user": {}, + "custom": "Pasirinktinis", + "@custom": {}, + "confirmMatrixId": "Norėdami ištrinti savo paskyrą, patvirtinkite savo Matrix ID.", + "@confirmMatrixId": {}, + "supposedMxid": "Tai turėtų būti {mxid}", + "@supposedMxid": { + "type": "text", + "placeholders": { + "mxid": {} + } + }, + "dehydrate": "Eksportuoti sesiją ir išvalyti įrenginį", + "@dehydrate": {}, + "dehydrateTor": "TOR Naudotojai: Eksportuoti sesiją", + "@dehydrateTor": {}, + "hydrateTor": "TOR Naudotojai: Importuoti sesijos eksportą", + "@hydrateTor": {}, + "hydrate": "Atkurti iš atsarginės kopijos failo", + "@hydrate": {}, + "pleaseEnterRecoveryKey": "Įveskite savo atkūrimo raktą:", + "@pleaseEnterRecoveryKey": {}, + "recoveryKey": "Atkūrimo raktas", + "@recoveryKey": {}, + "recoveryKeyLost": "Pamestas atkūrimo raktas?", + "@recoveryKeyLost": {}, + "indexedDbErrorLong": "Deja, pagal numatytuosius nustatymus žinučių saugojimas privačiame režime nėra įjungtas.\nPrašome apsilankyti\n - about:config\n - nustatykite dom.indexedDB.privateBrowsing.enabled į true\nPriešingu atveju FluffyChat paleisti neįmanoma.", + "@indexedDbErrorLong": {}, + "countFiles": "{count} failai", + "@countFiles": { + "placeholders": { + "count": {} + } + }, + "storeInSecureStorageDescription": "Atkūrimo raktą laikyti saugioje šio prietaiso saugykloje.", + "@storeInSecureStorageDescription": {}, + "saveKeyManuallyDescription": "Įrašykite šį raktą rankiniu būdu, įjungę sistemos bendrinimo dialogo langą arba iškarpinę.", + "@saveKeyManuallyDescription": {}, + "users": "Vartotojai", + "@users": {}, + "storeSecurlyOnThisDevice": "Saugiai laikyti šiame prietaise", + "@storeSecurlyOnThisDevice": {}, + "unlockOldMessages": "Atrakinti senas žinutes", + "@unlockOldMessages": {}, + "storeInAndroidKeystore": "Saugoti Android raktų saugykloje", + "@storeInAndroidKeystore": {}, + "indexedDbErrorTitle": "Privataus režimo problemos", + "@indexedDbErrorTitle": {}, + "noKeyForThisMessage": "Taip gali atsitikti, jei žinutė buvo išsiųsta prieš prisijungiant prie paskyros šiame prietaise.\n\nTaip pat gali būti, kad siuntėjas užblokavo jūsų prietaisą arba kažkas sutriko su interneto ryšiu.\n\nAr galite perskaityti žinutę kitoje sesijoje? Tada galite perkelti žinutę iš jos! Eikite į Nustatymai > Prietaisai ir įsitikinkite, kad jūsų prietaisai patvirtino vienas kitą. Kai kitą kartą atidarysite kambarį ir abi sesijos bus pirmame plane, raktai bus perduoti automatiškai.\n\nNenorite prarasti raktų atsijungdami arba keisdami įrenginius? Įsitikinkite, kad nustatymuose įjungėte pokalbių atsarginę kopiją.", + "@noKeyForThisMessage": {}, + "foregroundServiceRunning": "Šis pranešimas rodomas, kai veikia pirmojo plano paslauga.", + "@foregroundServiceRunning": {}, + "screenSharingTitle": "ekrano bendrinimas", + "@screenSharingTitle": {}, + "appearOnTopDetails": "Leidžia programėlę rodyti viršuje (nebūtina, jei jau esate nustatę Fluffychat kaip skambinimo paskyrą)", + "@appearOnTopDetails": {}, + "otherCallingPermissions": "Mikrofonas, kamera ir kiti FluffyChat leidimai", + "@otherCallingPermissions": {}, + "whyIsThisMessageEncrypted": "Kodėl ši žinutė neperskaitoma?", + "@whyIsThisMessageEncrypted": {}, + "newGroup": "Nauja grupė", + "@newGroup": {}, + "screenSharingDetail": "Bendrinate savo ekraną per FuffyChat", + "@screenSharingDetail": {}, + "numChats": "{number} pokalbiai", + "@numChats": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "hideUnimportantStateEvents": "Slėpti nesvarbius būsenos įvykius", + "@hideUnimportantStateEvents": {} +} diff --git a/assets/l10n/intl_lv.arb b/assets/l10n/intl_lv.arb index 03543548d..5c11ff97f 100644 --- a/assets/l10n/intl_lv.arb +++ b/assets/l10n/intl_lv.arb @@ -740,10 +740,6 @@ }, "signInWithPassword": "Pieteikties ar paroli", "@signInWithPassword": {}, - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, "lastActiveAgo": "Pēdējoreiz redzēts: {localizedTimeShort}", "@lastActiveAgo": { "type": "text", @@ -840,10 +836,6 @@ }, "editBundlesForAccount": "Labot šī konta komplektus", "@editBundlesForAccount": {}, - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, "enableEncryption": "Iespējot šifrēšanu", "@enableEncryption": { "type": "text", @@ -1114,10 +1106,6 @@ "joinRules": {} } }, - "@ignore": { - "type": "text", - "placeholders": {} - }, "recording": "Ieraksta", "@recording": { "type": "text", @@ -1537,10 +1525,6 @@ "type": "text", "placeholders": {} }, - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, "dehydrateTorLong": "TOR lietotājiem ir ieteicams izgūt sesiju pirms loga aizvēršanas.", "@dehydrateTorLong": {}, "yourPublicKey": "Tava publiskā atslēga", @@ -2683,5 +2667,24 @@ "count": {} }, "verifyOtherDeviceDescription": "Kad apliecini citu ierīci, šīs ierīces var apmainīt atslēgas, palielinot vispārējo drošību. 💪 Kad uzsāc apliecināšanu, abās ierīcēs lietotnē parādīsies uznirstošais logs. Tajā būs redzamas dažādas emocijzīmes vai skaitļi, kas jāsalīdzina abās ierīcēs. Vislabāk, ja abas ierīces ir pieejams, pirms tiek uzsākta apliecināšana. 🤳", - "@verifyOtherDeviceDescription": {} + "@verifyOtherDeviceDescription": {}, + "swipeRightToLeftToReply": "Pavilkt pa labi, lai atbildētu", + "@swipeRightToLeftToReply": {}, + "searchIn": "Meklēt tērzēšanā \"{chat}\"...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "searchMore": "Meklēt vairāk...", + "@searchMore": {}, + "gallery": "Galerija", + "@gallery": {}, + "files": "Datnes", + "@files": {}, + "restricted": "Ierobežots", + "@restricted": {}, + "knockRestricted": "Pieklauvēt ierobežotajiem", + "@knockRestricted": {} } diff --git a/assets/l10n/intl_nb.arb b/assets/l10n/intl_nb.arb index 660517c76..3835e0b76 100644 --- a/assets/l10n/intl_nb.arb +++ b/assets/l10n/intl_nb.arb @@ -1648,537 +1648,6 @@ "type": "text", "placeholders": {} }, - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@chats": { - "type": "text", - "placeholders": {} - }, - "@widgetVideo": {}, - "@dismiss": {}, - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "@reportErrorDescription": {}, - "@addAccount": {}, - "@chatHasBeenAddedToThisSpace": {}, - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "@unsupportedAndroidVersion": {}, - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "@widgetJitsi": {}, - "@messageType": {}, - "@indexedDbErrorLong": {}, - "@oneClientLoggedOut": {}, - "@startFirstChat": {}, - "@callingAccount": {}, - "@setColorTheme": {}, - "@nextAccount": {}, - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "@allSpaces": {}, - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "@user": {}, - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "@youAcceptedTheInvitation": {}, - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "@banUserDescription": {}, - "@widgetEtherpad": {}, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "@unbanUserDescription": {}, - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "@youRejectedTheInvitation": {}, - "@otherCallingPermissions": {}, - "@messagesStyle": {}, - "@link": {}, - "@widgetUrlError": {}, - "@emailOrUsername": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "@enterSpace": {}, - "@encryptThisChat": {}, - "@previousAccount": {}, - "@reopenChat": {}, - "@pleaseEnterRecoveryKey": {}, - "@widgetNameError": {}, - "@addToBundle": {}, - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "@addWidget": {}, - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "@noKeyForThisMessage": {}, - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "@commandHint_markasgroup": {}, - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "@hydrateTor": {}, - "@pushNotificationsNotAvailable": {}, - "@storeInAppleKeyChain": {}, - "@hydrate": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "@sender": {}, - "@storeInAndroidKeystore": {}, - "@signInWithPassword": {}, - "@makeAdminDescription": {}, - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "@saveKeyManuallyDescription": {}, - "@editBundlesForAccount": {}, - "@whyIsThisMessageEncrypted": {}, - "@setChatDescription": {}, - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "@importFromZipFile": {}, - "@or": { - "type": "text", - "placeholders": {} - }, - "@dehydrateWarning": {}, - "@noOtherDevicesFound": {}, - "@yourChatBackupHasBeenSetUp": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@videoCallsBetaWarning": {}, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@fileIsTooBigForServer": {}, - "@homeserver": {}, - "@people": { - "type": "text", - "placeholders": {} - }, - "@verified": { - "type": "text", - "placeholders": {} - }, - "@callingPermissions": {}, - "@readUpToHere": {}, - "@start": {}, - "@register": { - "type": "text", - "placeholders": {} - }, - "@unlockOldMessages": {}, - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@optionalRedactReason": {}, - "@dehydrate": {}, - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "@sendAsText": { - "type": "text" - }, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@commandInvalid": { - "type": "text" - }, - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "@experimentalVideoCalls": {}, - "@pleaseEnterRecoveryKeyDescription": {}, - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "@appearOnTopDetails": {}, - "@enterRoom": {}, - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "@reportUser": {}, - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "@confirmEventUnpin": {}, - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "@redactMessageDescription": {}, - "@recoveryKey": {}, - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "@invalidInput": {}, - "@dehydrateTorLong": {}, - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "@doNotShowAgain": {}, - "@report": {}, - "@unverified": {}, - "@serverRequiresEmail": {}, - "@hideUnimportantStateEvents": {}, - "@screenSharingTitle": {}, - "@widgetCustom": {}, - "@addToSpaceDescription": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "@addChatDescription": {}, - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@publish": {}, - "@openLinkInBrowser": {}, - "@clearArchive": {}, - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "@messageInfo": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@foregroundServiceRunning": {}, - "@voiceCall": {}, - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "@noChatDescriptionYet": {}, - "@removeFromBundle": {}, - "@confirmMatrixId": {}, - "@learnMore": {}, "notAnImage": "Ikke en bildefil.", - "@notAnImage": {}, - "@users": {}, - "@openGallery": {}, - "@chatDescriptionHasBeenChanged": {}, - "@newGroup": {}, - "@bundleName": {}, - "@dehydrateTor": {}, - "@removeFromSpace": {}, - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "@roomUpgradeDescription": {}, - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "@scanQrCode": {}, - "@pleaseEnterANumber": {}, - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "@profileNotFound": {}, - "@jump": {}, - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "@sorryThatsNotPossible": {}, - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "@shareInviteLink": {}, - "@commandHint_markasdm": {}, - "@recoveryKeyLost": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@deviceKeys": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@youJoinedTheChat": {}, - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "@markAsRead": {}, - "@widgetName": {}, - "@errorAddingWidget": {}, - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "@commandHint_hug": {}, - "@replace": {}, - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "@newSpace": {}, - "@emojis": {}, - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@hydrateTorLong": {}, - "@time": {}, - "@custom": {}, - "@noBackupWarning": {}, - "@storeInSecureStorageDescription": {}, - "@openChat": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@pinMessage": {}, - "@invite": {}, - "@enableMultiAccounts": {}, - "@indexedDbErrorTitle": {}, - "@unsupportedAndroidVersionLong": {}, - "@storeSecurlyOnThisDevice": {}, - "@screenSharingDetail": {}, - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "@placeCall": {} + "@notAnImage": {} } diff --git a/assets/l10n/intl_nl.arb b/assets/l10n/intl_nl.arb index 67d79c2b5..9bc789c00 100644 --- a/assets/l10n/intl_nl.arb +++ b/assets/l10n/intl_nl.arb @@ -562,7 +562,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "Standaardmachtigingsniveau", + "defaultPermissionLevel": "Standaard machtigingsniveau voor nieuwe personen", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -2313,7 +2313,7 @@ "@replace": {}, "report": "rapporteer", "@report": {}, - "reportErrorDescription": "Oh nee. Er is iets misgegaan. Probeer het later nog eens. Als je wilt, kun je de bug rapporteren aan de ontwikkelaars.", + "reportErrorDescription": "😭 Oh nee. Er is iets misgegaan. Probeer het later nog eens. Als je wilt, kun je de bug rapporteren aan de ontwikkelaars.", "@reportErrorDescription": {}, "sendTypingNotifications": "Typemeldingen verzenden", "@sendTypingNotifications": {}, @@ -2349,7 +2349,7 @@ "@inviteContactToGroupQuestion": {}, "optionalRedactReason": "(Optioneel) Reden voor aanpassing van dit bericht...", "@optionalRedactReason": {}, - "addChatDescription": "Voeg een chatbeschrijving toe", + "addChatDescription": "Voeg een chatbeschrijving toe...", "@addChatDescription": {}, "invalidServerName": "Foute servernaam", "@invalidServerName": {}, @@ -2404,7 +2404,7 @@ "@makeAdminDescription": {}, "archiveRoomDescription": "De chat zal naar het archief worden verplaatst. Andere personen zullen in staat zijn te zien dat je de chat hebt verlaten.", "@archiveRoomDescription": {}, - "hasKnocked": "{user} heeft geklopt", + "hasKnocked": "🚪 {user} heeft geklopt", "@hasKnocked": { "placeholders": { "user": {} @@ -2417,5 +2417,179 @@ "pleaseEnterANumber": "Vul een getal in groter dan 0", "@pleaseEnterANumber": {}, "kickUserDescription": "De persoon is verwijderd uit de chat, maar is niet verbannen. In publieke chats kan de persoon op elk moment opnieuw deelnemen.", - "@kickUserDescription": {} + "@kickUserDescription": {}, + "alwaysUse24HourFormat": "true", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "joinSpace": "Deelname aan space", + "@joinSpace": {}, + "block": "Blokkeren", + "@block": {}, + "blockedUsers": "Geblokkeerde personen", + "@blockedUsers": {}, + "presenceStyle": "Aanwezigheid:", + "@presenceStyle": { + "type": "text", + "placeholders": {} + }, + "searchChatsRooms": "Zoek naar #chats, @personen...", + "@searchChatsRooms": {}, + "swipeRightToLeftToReply": "Veeg van rechts naar links om te reageren", + "@swipeRightToLeftToReply": {}, + "calls": "Gesprekken", + "@calls": {}, + "customEmojisAndStickers": "Aangepaste emojis and stickers", + "@customEmojisAndStickers": {}, + "accessAndVisibilityDescription": "Wie mag meedoen in deze chat en hoe de chat ontdekt kan worden.", + "@accessAndVisibilityDescription": {}, + "customEmojisAndStickersBody": "Voeg toe of deel aangepaste emojis of stickers die gebruikt kunnen worden in elke chat.", + "@customEmojisAndStickersBody": {}, + "hideRedactedMessages": "Verberg verwijderde berichten", + "@hideRedactedMessages": {}, + "hideRedactedMessagesBody": "Als iemand een bericht verwijdert, is dit bericht niet meer zichtbaar in de chat.", + "@hideRedactedMessagesBody": {}, + "hideInvalidOrUnknownMessageFormats": "Verberg ongeldige of onbekende berichtformaten", + "@hideInvalidOrUnknownMessageFormats": {}, + "passwordRecoverySettings": "Wachtwoord herstel instellingen", + "@passwordRecoverySettings": {}, + "youInvitedToBy": "📩 Je bent uitgenodigd via een link voor:\n{alias}", + "@youInvitedToBy": { + "placeholders": { + "alias": {} + } + }, + "knock": "Kloppen", + "@knock": {}, + "overview": "Overzicht", + "@overview": {}, + "hidePresences": "Verberg Status Lijst?", + "@hidePresences": {}, + "noOneCanJoin": "Niemand kan deelnemen", + "@noOneCanJoin": {}, + "yourGlobalUserIdIs": "Je globale gebruikers-ID is: ", + "@yourGlobalUserIdIs": {}, + "appLockDescription": "Vergendel de app wanneer het niet gebruikt wordt met een pincode", + "@appLockDescription": {}, + "globalChatId": "Globale chat ID", + "@globalChatId": {}, + "accessAndVisibility": "Toegang en zichtbaarheid", + "@accessAndVisibility": {}, + "invitedBy": "📩 Uitgenodigd door: {user}", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "publicSpaces": "Publieke spaces", + "@publicSpaces": {}, + "blockUsername": "Negeer gebruikersnaam", + "@blockUsername": {}, + "publicChatAddresses": "Publieke chat adressen", + "@publicChatAddresses": {}, + "createNewAddress": "Creëer nieuw adres", + "@createNewAddress": {}, + "countChatsAndCountParticipants": "{chats} chats en {participants} deelnemers", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "noMoreChatsFound": "Geen chats gevonden...", + "@noMoreChatsFound": {}, + "joinedChats": "Deelnemende chats", + "@joinedChats": {}, + "knocking": "Kloppen", + "@knocking": {}, + "space": "Space", + "@space": {}, + "spaces": "Spaces", + "@spaces": {}, + "unread": "Zet als ongelezen", + "@unread": {}, + "databaseBuildErrorBody": "Het aanmaken van de SQlite database is mislukt. De app probeert nu een traditionele database te gebruiken. Meldt alsjeblieft deze fout aan de ontwikkelaars via deze {url}. De foutmelding is: {error}", + "@databaseBuildErrorBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "groupName": "Groepsnaam", + "@groupName": {}, + "changeGeneralChatSettings": "Wijzig algemene chat instellingen", + "@changeGeneralChatSettings": {}, + "restricted": "Beperkt", + "@restricted": {}, + "searchForUsers": "Zoek naar @personen...", + "@searchForUsers": {}, + "searchMore": "Zoek meer...", + "@searchMore": {}, + "noPublicLinkHasBeenCreatedYet": "Publieke link is nog niet gecreëerd", + "@noPublicLinkHasBeenCreatedYet": {}, + "groupCanBeFoundViaSearch": "Groep kan gevonden worden via zoeken", + "@groupCanBeFoundViaSearch": {}, + "searchIn": "Zoek in chat \"{chat}\"...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "files": "Bestanden", + "@files": {}, + "unreadChatsInApp": "{appname}: {unread} ongelezen chats", + "@unreadChatsInApp": { + "type": "text", + "placeholders": { + "appname": {}, + "unread": {} + } + }, + "noDatabaseEncryption": "Database versleuteling is niet ondersteund op dit platform", + "@noDatabaseEncryption": {}, + "thereAreCountUsersBlocked": "Nu zijn er {count} personen geblokkeerd.", + "@thereAreCountUsersBlocked": { + "type": "text", + "count": {} + }, + "markAsUnread": "Markeer als ongelezen", + "@markAsUnread": {}, + "userLevel": "{level} - Persoon", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - Moderator", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - Administrator", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "stickers": "Stickers", + "@stickers": {}, + "nothingFound": "Niets gevonden...", + "@nothingFound": {}, + "gallery": "Gallerij", + "@gallery": {}, + "transparent": "Transparant", + "@transparent": {}, + "incomingMessages": "Inkomende berichten", + "@incomingMessages": {}, + "discover": "Ontdek", + "@discover": {}, + "commandHint_ignore": "Negeer de gegeven matrix ID", + "@commandHint_ignore": {} } diff --git a/assets/l10n/intl_pl.arb b/assets/l10n/intl_pl.arb index b8e6517e2..506b85f6d 100644 --- a/assets/l10n/intl_pl.arb +++ b/assets/l10n/intl_pl.arb @@ -2393,23 +2393,44 @@ "@importNow": {}, "invite": "Zaproszenie", "@invite": {}, - "@banUserDescription": {}, - "@removeDevicesDescription": {}, - "@unbanUserDescription": {}, - "@pushNotificationsNotAvailable": {}, - "@makeAdminDescription": {}, - "@archiveRoomDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@learnMore": {}, - "@roomUpgradeDescription": {}, - "@pleaseEnterANumber": {}, - "@kickUserDescription": {}, - "block": "zablokuj", + "block": "Zablokuj", "@block": {}, "blockedUsers": "Zablokowani użytkownicy", - "@blockedUsers": {} + "@blockedUsers": {}, + "blockUsername": "Ignoruj użytkownika", + "@blockUsername": {}, + "publicLink": "Link publiczny", + "@publicLink": {}, + "transparent": "Przezroczystość", + "@transparent": {}, + "select": "Zaznacz", + "@select": {}, + "calls": "Połączenia", + "@calls": {}, + "overview": "Podsumowanie", + "@overview": {}, + "learnMore": "Dowiedz się więcej", + "@learnMore": {}, + "groupName": "Nazwa grupy", + "@groupName": {}, + "startConversation": "Rozpocznij rozmowę", + "@startConversation": {}, + "newPassword": "Nowe hasło", + "@newPassword": {}, + "thisDevice": "To urządzenie:", + "@thisDevice": {}, + "gallery": "Galeria", + "@gallery": {}, + "files": "Pliki", + "@files": {}, + "discover": "Odkrywaj", + "@discover": {}, + "restricted": "Ograniczone", + "@restricted": {}, + "decline": "Odmów", + "@decline": {}, + "nothingFound": "Nic nie odnaleziono...", + "@nothingFound": {}, + "stickers": "Naklejki", + "@stickers": {} } diff --git a/assets/l10n/intl_pt_BR.arb b/assets/l10n/intl_pt_BR.arb index cf700209b..95ba83675 100644 --- a/assets/l10n/intl_pt_BR.arb +++ b/assets/l10n/intl_pt_BR.arb @@ -2688,5 +2688,22 @@ "createNewAddress": "Criar um novo endereço", "@createNewAddress": {}, "knock": "Bater na porta", - "@knock": {} + "@knock": {}, + "searchIn": "Pesquisar em {chat}...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "restricted": "Restrito", + "@restricted": {}, + "knockRestricted": "Bater na porta restrito", + "@knockRestricted": {}, + "searchMore": "Pesquisar mais...", + "@searchMore": {}, + "gallery": "Galeria", + "@gallery": {}, + "files": "Arquivos", + "@files": {} } diff --git a/assets/l10n/intl_pt_PT.arb b/assets/l10n/intl_pt_PT.arb index 9db37c78e..1cdce9ee1 100644 --- a/assets/l10n/intl_pt_PT.arb +++ b/assets/l10n/intl_pt_PT.arb @@ -1,2182 +1,1569 @@ { - "repeatPassword": "Repete a palavra-passe", - "@repeatPassword": {}, - "about": "Acerca de", - "@about": { - "type": "text", - "placeholders": {} - }, - "accept": "Aceitar", - "@accept": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "{username} aceitou o convite", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "Conta", - "@account": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "{username} ativou encriptação ponta-a-ponta", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "addEmail": "Adicionar correio eletrónico", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "addToSpace": "Adicionar ao espaço", - "@addToSpace": {}, - "admin": "Admin", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "alcunha", - "@alias": { - "type": "text", - "placeholders": {} - }, - "all": "Todos(as)", - "@all": { - "type": "text", - "placeholders": {} - }, - "allChats": "Todas as conversas", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "{senderName} atendeu a chamada", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "Qualquer pessoa pode entrar", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "archive": "Arquivo", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "Todos os visitantes podem entrar", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "Tens a certeza?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "areYouSureYouWantToLogout": "Tens a certeza que queres sair?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "Para poderes assinar a outra pessoa, por favor, insere a tua senha de armazenamento seguro ou a chave de recuperação.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "Aceitar este pedido de verificação de {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "autoplayImages": "Automaticamente reproduzir autocolantes e emotes animados", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "sendOnEnter": "Enviar com Enter", - "@sendOnEnter": {}, - "badServerVersionsException": "O servidor suporta as versões Spec:\n{serverVersions}\nMas esta aplicação apenas suporta {suportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "badServerLoginTypesException": "O servidor suporta os tipos de início de sessão:\n{serverVersions}\nMas esta aplicação apenas suporta:\n{suportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "banFromChat": "Banir da conversa", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "Banido(a)", - "@banned": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "{username} baniu {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "blockDevice": "Bloquear dispositivo", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "Bloqueado", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "botMessages": "Mensagens de robôs", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "cancel": "Cancelar", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "cantOpenUri": "Não é possível abrir o URI {uri}", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "changeDeviceName": "Alterar nome do dispositivo", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheChatPermissions": "{username} alterou as permissões da conversa", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "{username} alterou o seu nome para: '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} alterou as regras de acesso de visitantes para: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username} alterou as regras de entrada", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "{username} alterou as regras de entrada para: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheProfileAvatar": "{username} alterou o seu avatar", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "{username} alterou as alcunhas da sala", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomInvitationLink": "{username} alterou a ligação de convite", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changePassword": "Alterar palavra-passe", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "changeTheHomeserver": "Alterar o servidor", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "Alterar o teu estilo", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "Alterar o nome do grupo", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "Alterar o teu avatar", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "A encriptação foi corrompida", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chat": "Conversa", - "@chat": { - "type": "text", - "placeholders": {} - }, - "yourChatBackupHasBeenSetUp": "A cópia de segurança foi configurada.", - "@yourChatBackupHasBeenSetUp": {}, - "chatBackup": "Cópia de segurança de conversas", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "A tuas mensagens antigas estão protegidas com uma chave de recuperação. Por favor, certifica-te que não a perdes.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "Detalhes de conversa", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "A conversa foi adicionada a este espaço", - "@chatHasBeenAddedToThisSpace": {}, - "chats": "Conversas", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "Escolhe uma palavra-passe forte", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "Limpar arquivo", - "@clearArchive": {}, - "close": "Fechar", - "@close": { - "type": "text", - "placeholders": {} - }, - "commandHint_ban": "Banir o utilizador dado desta sala", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_html": "Enviar texto formatado com HTML", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "Convidar o utilizador dado a esta sala", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_join": "Entrar na sala dada", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_kick": "Remover o utilizador dado desta sala", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_leave": "Sair desta sala", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_me": "Descreve-te", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "commandHint_myroomavatar": "Definir a tua imagem para esta sala (por mxc-uri)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_myroomnick": "Definir o teu nome para esta sala", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_op": "Definir o nível de poder do utilizador dado (por omissão: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_plain": "Enviar texto não formatado", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_react": "Enviar respostas como reações", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandHint_send": "Enviar texto", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandHint_unban": "Perdoar o utilizador dado", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "commandInvalid": "Comando inválido", - "@commandInvalid": { - "type": "text" - }, - "commandMissing": "{command} não é um comando.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "compareEmojiMatch": "Compara e certifica-te que os emojis que se seguem correspondem aos do outro dispositivo:", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Compara e certifica-te que os números que se seguem correspondem aos do outro dispositivo:", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "configureChat": "Configurar conversa", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "confirm": "Confirmar", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "connect": "Ligar", - "@connect": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "O contacto foi convidado para o grupo", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "Contém nome de exibição", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "Contém nome de utilizador", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "O conteúdo foi denunciado aos admins do servidor", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "Copiado para a área de transferência", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "copy": "Copiar", - "@copy": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "Copiar para a área de transferência", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Não foi possível desencriptar mensagem: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "countParticipants": "{count} participantes", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "create": "Criar", - "@create": { - "type": "text", - "placeholders": {} - }, - "createdTheChat": "{username} criou a conversa", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "createNewSpace": "Novo espaço", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "currentlyActive": "Ativo(a) agora", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "Escuro", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "dateAndTimeOfDay": "{date} às {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "dateWithoutYear": "{day}-{month}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateWithYear": "{day}-{month}-{year}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "deactivateAccountWarning": "Isto irá desativar a tua conta. Não é reversível! Tens a certeza?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "Nível de permissão normal", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "delete": "Eliminar", - "@delete": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "Eliminar conta", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "Eliminar mensagem", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "device": "Dispositivo", - "@device": { - "type": "text", - "placeholders": {} - }, - "deviceId": "ID de dispositivo", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "Dispositivos", - "@devices": { - "type": "text", - "placeholders": {} - }, - "directChats": "Conversas diretas", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "Nome de exibição alterado", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "Descarregar ficheiro", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "edit": "Editar", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "Editar servidores bloqueados", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "Editar nome de exibição", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "Editar alcunhas da sala", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "Editar avatar da sala", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Emote já existente!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "Código de emote inválido!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "Pacotes de emotes da sala", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Configurações de emotes", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "emoteShortcode": "Código do emote", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Precisas de escolher um código de emote e uma imagem!", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "Conversa vazia", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "Ativar pacote de emotes globalmente", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "Ativar encriptação", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "enableEncryptionWarning": "Nunca mais poderás desativar a encriptação. Tens a certeza?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "encrypted": "Encriptada", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "encryption": "Encriptação", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "encryptionNotEnabled": "A encriptação não está ativada", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "{senderName} terminou a chamada", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "enterAnEmailAddress": "Insere um endereço de correio eletrónico", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "homeserver": "Servidor", - "@homeserver": {}, - "enterYourHomeserver": "Insere o teu servidor", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "errorObtainingLocation": "Erro ao obter localização: {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "everythingReady": "Tudo a postos!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "Extremamente ofensivo", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "fileName": "Nome do ficheiro", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "fontSize": "Tamanho da letra", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "forward": "Reencaminhar", - "@forward": { - "type": "text", - "placeholders": {} - }, - "goToTheNewRoom": "Ir para a nova sala", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "group": "Grupo", - "@group": { - "type": "text", - "placeholders": {} - }, - "groupIsPublic": "O grupo é público", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "groups": "Grupos", - "@groups": { - "type": "text", - "placeholders": {} - }, - "groupWith": "Grupo com {displayname}", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "guestsAreForbidden": "São proibidos visitantes", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "Podem entrar visitantes", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "hasWithdrawnTheInvitationFor": "{username} revogou o convite para {targetName}", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "help": "Ajuda", - "@help": { - "type": "text", - "placeholders": {} - }, - "hideRedactedEvents": "Esconder eventos eliminados", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "Esconder eventos desconhecidos", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "howOffensiveIsThisContent": "Quão ofensivo é este conteúdo?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "id": "ID", - "@id": { - "type": "text", - "placeholders": {} - }, - "identity": "Identidade", - "@identity": { - "type": "text", - "placeholders": {} - }, - "ignore": "Ignorar", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "Utilizadores ignorados", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "Eu cliquei na ligação", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "incorrectPassphraseOrKey": "Senha ou chave de recuperação incorretos", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "Inofensivo", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "Convidar contacto", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "Convidar contacto para {groupName}", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "invited": "Convidado(a)", - "@invited": { - "type": "text", - "placeholders": {} - }, - "invitedUser": "{username} convidou {targetName}", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "invitedUsersOnly": "Utilizadores(as) convidados(as) apenas", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "inviteForMe": "Convite para mim", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "inviteText": "{username} convidou-te para o FluffyChat.\n1. Instala o FluffyChat: https://fluffychat.im\n2. Regista-te ou inicia sessão.\n3. Abre a ligação de convite: {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "isTyping": "está a escrever…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "joinedTheChat": "{username} entrou na conversa", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "joinRoom": "Entrar na sala", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "kicked": "{username} expulsou {targetName}", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickedAndBanned": "{username} expulsou e baniu {targetName}", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickFromChat": "Expulsar da conversa", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "lastActiveAgo": "Ativo(a) pela última vez: {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "leave": "Sair", - "@leave": { - "type": "text", - "placeholders": {} - }, - "leftTheChat": "Saiu da conversa", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "license": "Licença", - "@license": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "Claro", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "loadCountMoreParticipants": "Carregar mais {count} participantes", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "loadingPleaseWait": "A carregar... Por favor aguarde.", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "loadMore": "Carregar mais…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "locationDisabledNotice": "Os serviços de localização estão desativados. Por favor, ativa-os para poder partilhar a sua localização.", - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "locationPermissionDeniedNotice": "Permissão de localização recusada. Por favor, concede permissão para poderes partilhar a tua posição.", - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "login": "Entrar", - "@login": { - "type": "text", - "placeholders": {} - }, - "logInTo": "Entrar em {homeserver}", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "logout": "Sair", - "@logout": { - "type": "text", - "placeholders": {} - }, - "memberChanges": "Alterações de membros", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "mention": "Mencionar", - "@mention": { - "type": "text", - "placeholders": {} - }, - "messages": "Mensagens", - "@messages": { - "type": "text", - "placeholders": {} - }, - "moderator": "Moderador", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "muteChat": "Silenciar conversa", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "Por favor,", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "newChat": "Nova conversa", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "Nova mensagem no FluffyChat", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "newVerificationRequest": "Novo pedido de verificação!", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "next": "Próximo", - "@next": { - "type": "text", - "placeholders": {} - }, - "no": "Não", - "@no": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "Nenhuma ligação ao servidor", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "noEmotesFound": "Nenhuns emotes encontrados. 😕", - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "Só podes ativar a encriptação quando a sala não for publicamente acessível.", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "noGoogleServicesWarning": "Parece que não tens nenhuns serviços da Google no seu telemóvel. É uma boa decisão para a sua privacidade! Para receber notificações instantâneas no FluffyChat, recomendamos que uses https://microg.org/ ou https://unifiedpush.org/.", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "noMatrixServer": "{server1} não é um servidor Matrix, usar {server2}?", - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "none": "Nenhum", - "@none": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "{username} alterou o avatar da conversa", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "{username} alterou a visibilidade do histórico para: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheChatDescriptionTo": "{username} alterou a descrição da conversa para: '{description}'", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheChatNameTo": "{username} alterou o nome da conversa para: '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheGuestAccessRules": "{username} alterou as regras de acesso de visitantes", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibility": "{username} alterou a visibilidade do histórico", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sendAMessage": "Enviar a mensagem", - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "sendAudio": "Enviar áudio", - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "sendAsText": "Enviar como texto", - "@sendAsText": { - "type": "text" - }, - "send": "Enviar", - "@send": { - "type": "text", - "placeholders": {} - }, - "appLock": "Bloqueio da aplicação", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "Ainda não adicionaste uma forma de recuperar a tua palavra-passe.", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "noPermission": "Sem permissão", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "Não foram encontradas nenhumas salas…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "notifications": "Notificações", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "notificationsEnabledForThisAccount": "Notificações ativadas para esta conta", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "numUsersTyping": "Estão {count} utilizadores(as) a escrever…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "obtainingLocation": "A obter localização…", - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "offensive": "Offensivo", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "offline": "Offline", - "@offline": { - "type": "text", - "placeholders": {} - }, - "ok": "ok", - "@ok": { - "type": "text", - "placeholders": {} - }, - "online": "Online", - "@online": { - "type": "text", - "placeholders": {} - }, - "onlineKeyBackupEnabled": "A cópia de segurança online de chaves está ativada", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "oopsPushError": "Ups! Infelizmente, ocorreu um erro ao configurar as notificações instantâneas.", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "Ups, algo correu mal…", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "Abrir aplicação para ler mensagens", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "openCamera": "Abrir câmara", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "oneClientLoggedOut": "Um dos teus clientes terminou sessão", - "@oneClientLoggedOut": {}, - "addAccount": "Adicionar conta", - "@addAccount": {}, - "editBundlesForAccount": "Editar pacotes para esta conta", - "@editBundlesForAccount": {}, - "addToBundle": "Adicionar ao pacote", - "@addToBundle": {}, - "removeFromBundle": "Remover deste pacote", - "@removeFromBundle": {}, - "bundleName": "Nome do pacote", - "@bundleName": {}, - "enableMultiAccounts": "(BETA) Ativar múltiplas contas neste dispositivo", - "@enableMultiAccounts": {}, - "openInMaps": "Abrir nos mapas", - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "link": "Ligação", - "@link": {}, - "serverRequiresEmail": "Este servidor precisa de validar o teu endereço de correio eletrónico para o registo.", - "@serverRequiresEmail": {}, - "or": "Ou", - "@or": { - "type": "text", - "placeholders": {} - }, - "participant": "Participante", - "@participant": { - "type": "text", - "placeholders": {} - }, - "passphraseOrKey": "senha ou chave de recuperação", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "password": "Palavra-passe", - "@password": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "Palavra-passe esquecida", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "A palavra-passe foi alterada", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "passwordRecovery": "Recuperação de palavra-passe", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "people": "Pessoas", - "@people": { - "type": "text", - "placeholders": {} - }, - "pickImage": "Escolher uma imagem", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "pin": "Afixar", - "@pin": { - "type": "text", - "placeholders": {} - }, - "play": "Reproduzir {fileName}", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "pleaseChoose": "Por favor, escolhe", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "pleaseChooseAPasscode": "Por favor, escolhe um código-passe", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pleaseClickOnLink": "Por favor, clica na ligação no correio eletrónico e depois continua.", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "Por favor, insere 4 dígitos ou deixa vazio para desativar o bloqueio da aplicação.", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "Por favor, insere a tua palavra-passe", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "Por favor, insere o teu código", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "Por favor, insere o teu nome de utilizador", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "pleaseFollowInstructionsOnWeb": "Por favor, segue as instruções no website e clica em \"Seguinte\".", - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "privacy": "Privacidade", - "@privacy": { - "type": "text", - "placeholders": {} - }, - "publicRooms": "Salas públicas", - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "reason": "Razão", - "@reason": { - "type": "text", - "placeholders": {} - }, - "redactedAnEvent": "{username} eliminou um evento", - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "recording": "A gravar", - "@recording": { - "type": "text", - "placeholders": {} - }, - "redactMessage": "Eliminar mensagem", - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "register": "Registar", - "@register": { - "type": "text", - "placeholders": {} - }, - "reject": "Rejeitar", - "@reject": { - "type": "text", - "placeholders": {} - }, - "rejectedTheInvitation": "{username} rejeitou o convite", - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "rejoin": "Reentrar", - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "remove": "Remover", - "@remove": { - "type": "text", - "placeholders": {} - }, - "removeAllOtherDevices": "Remover todos os outros dispositivos", - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "removedBy": "Removido por {username}", - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removeDevice": "Remover dispositivo", - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "unbanFromChat": "Perdoar nesta conversa", - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "removeYourAvatar": "Remover o teu avatar", - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "renderRichContent": "Exibir conteúdo de mensagem rico", - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "replaceRoomWithNewerVersion": "Substituir sala com versão mais recente", - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "reply": "Responder", - "@reply": { - "type": "text", - "placeholders": {} - }, - "reportMessage": "Reportar mensagem", - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "requestPermission": "Pedir permissão", - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "roomHasBeenUpgraded": "A sala foi atualizada", - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "roomVersion": "Versão da sala", - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "saveFile": "Guardar ficheiro", - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "search": "Procurar", - "@search": { - "type": "text", - "placeholders": {} - }, - "security": "Segurança", - "@security": { - "type": "text", - "placeholders": {} - }, - "seenByUser": "Visto por {username}", - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sendFile": "Enviar ficheiro", - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "sendImage": "Enviar imagem", - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "sendMessages": "Enviar mensagens", - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "sendOriginal": "Enviar original", - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "sendSticker": "Enviar autocolante", - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "sendVideo": "Enviar vídeo", - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "sentAFile": "{username} enviar um ficheiro", - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAnAudio": "{username} enviar um áudio", - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAPicture": "{username} enviar uma imagem", - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentASticker": "{username} enviou um autocolante", - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAVideo": "{username} enviou um vídeo", - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "commandHint_clearcache": "Limpar cache", - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "commandHint_create": "Criar uma conversa de grupo vazia\nUsa --no-encryption para desativar a encriptação", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "commandHint_discardsession": "Descartar sessão", - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "commandHint_dm": "Iniciar uma conversa direta\nUsa --no-encryption para desativar a encriptação", - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "dehydrate": "Exportar sessão e limpar dispositivo", - "@dehydrate": {}, - "dehydrateWarning": "Esta ação não pode ser revertida. Assegura-te que guardas bem a cópia de segurança.", - "@dehydrateWarning": {}, - "hydrateTorLong": "Exportaste a tua sessão na última vez que estiveste no TOR? Importa-a rapidamente e continua a conversar.", - "@hydrateTorLong": {}, - "dehydrateTor": "Utilizadores do TOR: Exportar sessão", - "@dehydrateTor": {}, - "hydrate": "Restaurar a partir de cópia de segurança", - "@hydrate": {}, - "hydrateTor": "Utilizadores do TOR: Importar sessão", - "@hydrateTor": {}, - "dehydrateTorLong": "Para utilizadores do TOR, é recomendado exportar a sessão antes de fechar a janela.", - "@dehydrateTorLong": {}, - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@widgetVideo": {}, - "@dismiss": {}, - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "@reportErrorDescription": {}, - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "@unsupportedAndroidVersion": {}, - "@widgetJitsi": {}, - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "@messageType": {}, - "@indexedDbErrorLong": {}, - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "@startFirstChat": {}, - "@callingAccount": {}, - "@setColorTheme": {}, - "@nextAccount": {}, - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "@warning": { - "type": "text", - "placeholders": {} - }, - "@allSpaces": {}, - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "@user": {}, - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "@youAcceptedTheInvitation": {}, - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@banUserDescription": {}, - "@widgetEtherpad": {}, - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "@unbanUserDescription": {}, - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "@youRejectedTheInvitation": {}, - "@otherCallingPermissions": {}, - "@messagesStyle": {}, - "@widgetUrlError": {}, - "@emailOrUsername": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@enterSpace": {}, - "@encryptThisChat": {}, - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "@previousAccount": {}, - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "@reopenChat": {}, - "@pleaseEnterRecoveryKey": {}, - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "@widgetNameError": {}, - "@unpin": { - "type": "text", - "placeholders": {} - }, - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "@addWidget": {}, - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "@noKeyForThisMessage": {}, - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "@commandHint_markasgroup": {}, - "@pushNotificationsNotAvailable": {}, - "@storeInAppleKeyChain": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "@sender": {}, - "@storeInAndroidKeystore": {}, - "@signInWithPassword": {}, - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "@makeAdminDescription": {}, - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "@saveKeyManuallyDescription": {}, - "@whyIsThisMessageEncrypted": {}, - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "@setChatDescription": {}, - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "@importFromZipFile": {}, - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "@noOtherDevicesFound": {}, - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@submit": { - "type": "text", - "placeholders": {} - }, - "@videoCallsBetaWarning": {}, - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "@yes": { - "type": "text", - "placeholders": {} - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@username": { - "type": "text", - "placeholders": {} - }, - "@fileIsTooBigForServer": {}, - "@verified": { - "type": "text", - "placeholders": {} - }, - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "@callingPermissions": {}, - "@readUpToHere": {}, - "@start": {}, - "@unlockOldMessages": {}, - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@optionalRedactReason": {}, - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "@experimentalVideoCalls": {}, - "@pleaseEnterRecoveryKeyDescription": {}, - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "@skip": { - "type": "text", - "placeholders": {} - }, - "@appearOnTopDetails": {}, - "@enterRoom": {}, - "@reportUser": {}, - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "@confirmEventUnpin": {}, - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@redactMessageDescription": {}, - "@recoveryKey": {}, - "@invalidInput": {}, - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "@doNotShowAgain": {}, - "@report": {}, - "@status": { - "type": "text", - "placeholders": {} - }, - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "@unverified": {}, - "@hideUnimportantStateEvents": {}, - "@screenSharingTitle": {}, - "@widgetCustom": {}, - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@addToSpaceDescription": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "@addChatDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@publish": {}, - "@openLinkInBrowser": {}, - "@messageInfo": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "@foregroundServiceRunning": {}, - "@voiceCall": {}, - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "@noChatDescriptionYet": {}, - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "@confirmMatrixId": {}, - "@learnMore": {}, - "@you": { - "type": "text", - "placeholders": {} - }, - "@notAnImage": {}, - "@users": {}, - "@openGallery": {}, - "@chatDescriptionHasBeenChanged": {}, - "@newGroup": {}, - "@removeFromSpace": {}, - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "@roomUpgradeDescription": {}, - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "@scanQrCode": {}, - "@pleaseEnterANumber": {}, - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "@profileNotFound": {}, - "@jump": {}, - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "@sorryThatsNotPossible": {}, - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "@shareInviteLink": {}, - "@commandHint_markasdm": {}, - "@recoveryKeyLost": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@deviceKeys": {}, - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "@settings": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@youJoinedTheChat": {}, - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "@markAsRead": {}, - "@widgetName": {}, - "@errorAddingWidget": {}, - "@commandHint_hug": {}, - "@replace": {}, - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "@newSpace": {}, - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "@emojis": {}, - "@share": { - "type": "text", - "placeholders": {} - }, - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@time": {}, - "@custom": {}, - "@noBackupWarning": {}, - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "@verify": { - "type": "text", - "placeholders": {} - }, - "@storeInSecureStorageDescription": {}, - "@openChat": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "@pinMessage": {}, - "@invite": {}, - "@indexedDbErrorTitle": {}, - "@unsupportedAndroidVersionLong": {}, - "@storeSecurlyOnThisDevice": {}, - "@screenSharingDetail": {}, - "@placeCall": {} -} \ No newline at end of file + "repeatPassword": "Repete a palavra-passe", + "@repeatPassword": {}, + "about": "Acerca de", + "@about": { + "type": "text", + "placeholders": {} + }, + "accept": "Aceitar", + "@accept": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "{username} aceitou o convite", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "account": "Conta", + "@account": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "{username} ativou encriptação ponta-a-ponta", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "addEmail": "Adicionar correio eletrónico", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "addToSpace": "Adicionar ao espaço", + "@addToSpace": {}, + "admin": "Admin", + "@admin": { + "type": "text", + "placeholders": {} + }, + "alias": "alcunha", + "@alias": { + "type": "text", + "placeholders": {} + }, + "all": "Todos(as)", + "@all": { + "type": "text", + "placeholders": {} + }, + "allChats": "Todas as conversas", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "{senderName} atendeu a chamada", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "anyoneCanJoin": "Qualquer pessoa pode entrar", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "archive": "Arquivo", + "@archive": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "Todos os visitantes podem entrar", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "Tens a certeza?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "areYouSureYouWantToLogout": "Tens a certeza que queres sair?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "askSSSSSign": "Para poderes assinar a outra pessoa, por favor, insere a tua senha de armazenamento seguro ou a chave de recuperação.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "Aceitar este pedido de verificação de {username}?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "autoplayImages": "Automaticamente reproduzir autocolantes e emotes animados", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "sendOnEnter": "Enviar com Enter", + "@sendOnEnter": {}, + "badServerVersionsException": "O servidor suporta as versões Spec:\n{serverVersions}\nMas esta aplicação apenas suporta {suportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "badServerLoginTypesException": "O servidor suporta os tipos de início de sessão:\n{serverVersions}\nMas esta aplicação apenas suporta:\n{suportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "banFromChat": "Banir da conversa", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "banned": "Banido(a)", + "@banned": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "{username} baniu {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "blockDevice": "Bloquear dispositivo", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "blocked": "Bloqueado", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "botMessages": "Mensagens de robôs", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "cancel": "Cancelar", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "cantOpenUri": "Não é possível abrir o URI {uri}", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "changeDeviceName": "Alterar nome do dispositivo", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "changedTheChatPermissions": "{username} alterou as permissões da conversa", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "{username} alterou o seu nome para: '{displayname}'", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRulesTo": "{username} alterou as regras de acesso de visitantes para: {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRules": "{username} alterou as regras de entrada", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheJoinRulesTo": "{username} alterou as regras de entrada para: {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheProfileAvatar": "{username} alterou o seu avatar", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "{username} alterou as alcunhas da sala", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomInvitationLink": "{username} alterou a ligação de convite", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changePassword": "Alterar palavra-passe", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "changeTheHomeserver": "Alterar o servidor", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "Alterar o teu estilo", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "Alterar o nome do grupo", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "changeYourAvatar": "Alterar o teu avatar", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "channelCorruptedDecryptError": "A encriptação foi corrompida", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "chat": "Conversa", + "@chat": { + "type": "text", + "placeholders": {} + }, + "yourChatBackupHasBeenSetUp": "A cópia de segurança foi configurada.", + "@yourChatBackupHasBeenSetUp": {}, + "chatBackup": "Cópia de segurança de conversas", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "chatBackupDescription": "A tuas mensagens antigas estão protegidas com uma chave de recuperação. Por favor, certifica-te que não a perdes.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "chatDetails": "Detalhes de conversa", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chatHasBeenAddedToThisSpace": "A conversa foi adicionada a este espaço", + "@chatHasBeenAddedToThisSpace": {}, + "chats": "Conversas", + "@chats": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "Escolhe uma palavra-passe forte", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "clearArchive": "Limpar arquivo", + "@clearArchive": {}, + "close": "Fechar", + "@close": { + "type": "text", + "placeholders": {} + }, + "commandHint_ban": "Banir o utilizador dado desta sala", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_html": "Enviar texto formatado com HTML", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_invite": "Convidar o utilizador dado a esta sala", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "commandHint_join": "Entrar na sala dada", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_kick": "Remover o utilizador dado desta sala", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_leave": "Sair desta sala", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_me": "Descreve-te", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "commandHint_myroomavatar": "Definir a tua imagem para esta sala (por mxc-uri)", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_myroomnick": "Definir o teu nome para esta sala", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "commandHint_op": "Definir o nível de poder do utilizador dado (por omissão: 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_plain": "Enviar texto não formatado", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_react": "Enviar respostas como reações", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "commandHint_send": "Enviar texto", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "commandHint_unban": "Perdoar o utilizador dado", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "commandInvalid": "Comando inválido", + "@commandInvalid": { + "type": "text" + }, + "commandMissing": "{command} não é um comando.", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "compareEmojiMatch": "Compara e certifica-te que os emojis que se seguem correspondem aos do outro dispositivo:", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "Compara e certifica-te que os números que se seguem correspondem aos do outro dispositivo:", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "configureChat": "Configurar conversa", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "confirm": "Confirmar", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "connect": "Ligar", + "@connect": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "O contacto foi convidado para o grupo", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "Contém nome de exibição", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "containsUserName": "Contém nome de utilizador", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "O conteúdo foi denunciado aos admins do servidor", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "Copiado para a área de transferência", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "copy": "Copiar", + "@copy": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "Copiar para a área de transferência", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "Não foi possível desencriptar mensagem: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "countParticipants": "{count} participantes", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "create": "Criar", + "@create": { + "type": "text", + "placeholders": {} + }, + "createdTheChat": "{username} criou a conversa", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "createNewSpace": "Novo espaço", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "currentlyActive": "Ativo(a) agora", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "Escuro", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "dateAndTimeOfDay": "{date} às {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "dateWithoutYear": "{day}-{month}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "dateWithYear": "{day}-{month}-{year}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "deactivateAccountWarning": "Isto irá desativar a tua conta. Não é reversível! Tens a certeza?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "Nível de permissão normal", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "delete": "Eliminar", + "@delete": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "Eliminar conta", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "Eliminar mensagem", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "device": "Dispositivo", + "@device": { + "type": "text", + "placeholders": {} + }, + "deviceId": "ID de dispositivo", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "devices": "Dispositivos", + "@devices": { + "type": "text", + "placeholders": {} + }, + "directChats": "Conversas diretas", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "displaynameHasBeenChanged": "Nome de exibição alterado", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "Descarregar ficheiro", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "edit": "Editar", + "@edit": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "Editar servidores bloqueados", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "Editar nome de exibição", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "Editar alcunhas da sala", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "Editar avatar da sala", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "Emote já existente!", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "emoteInvalid": "Código de emote inválido!", + "@emoteInvalid": { + "type": "text", + "placeholders": {} + }, + "emotePacks": "Pacotes de emotes da sala", + "@emotePacks": { + "type": "text", + "placeholders": {} + }, + "emoteSettings": "Configurações de emotes", + "@emoteSettings": { + "type": "text", + "placeholders": {} + }, + "emoteShortcode": "Código do emote", + "@emoteShortcode": { + "type": "text", + "placeholders": {} + }, + "emoteWarnNeedToPick": "Precisas de escolher um código de emote e uma imagem!", + "@emoteWarnNeedToPick": { + "type": "text", + "placeholders": {} + }, + "emptyChat": "Conversa vazia", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "enableEmotesGlobally": "Ativar pacote de emotes globalmente", + "@enableEmotesGlobally": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "Ativar encriptação", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "enableEncryptionWarning": "Nunca mais poderás desativar a encriptação. Tens a certeza?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "encrypted": "Encriptada", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "encryption": "Encriptação", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "encryptionNotEnabled": "A encriptação não está ativada", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "{senderName} terminou a chamada", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "enterAnEmailAddress": "Insere um endereço de correio eletrónico", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "homeserver": "Servidor", + "@homeserver": {}, + "enterYourHomeserver": "Insere o teu servidor", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "errorObtainingLocation": "Erro ao obter localização: {error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "everythingReady": "Tudo a postos!", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "extremeOffensive": "Extremamente ofensivo", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "fileName": "Nome do ficheiro", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "fontSize": "Tamanho da letra", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "forward": "Reencaminhar", + "@forward": { + "type": "text", + "placeholders": {} + }, + "goToTheNewRoom": "Ir para a nova sala", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "group": "Grupo", + "@group": { + "type": "text", + "placeholders": {} + }, + "groupIsPublic": "O grupo é público", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "groups": "Grupos", + "@groups": { + "type": "text", + "placeholders": {} + }, + "groupWith": "Grupo com {displayname}", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "guestsAreForbidden": "São proibidos visitantes", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "Podem entrar visitantes", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "hasWithdrawnTheInvitationFor": "{username} revogou o convite para {targetName}", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "help": "Ajuda", + "@help": { + "type": "text", + "placeholders": {} + }, + "hideRedactedEvents": "Esconder eventos eliminados", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "Esconder eventos desconhecidos", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "howOffensiveIsThisContent": "Quão ofensivo é este conteúdo?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "id": "ID", + "@id": { + "type": "text", + "placeholders": {} + }, + "identity": "Identidade", + "@identity": { + "type": "text", + "placeholders": {} + }, + "ignore": "Ignorar", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "Utilizadores ignorados", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "Eu cliquei na ligação", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "incorrectPassphraseOrKey": "Senha ou chave de recuperação incorretos", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "Inofensivo", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "Convidar contacto", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "Convidar contacto para {groupName}", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "invited": "Convidado(a)", + "@invited": { + "type": "text", + "placeholders": {} + }, + "invitedUser": "{username} convidou {targetName}", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "invitedUsersOnly": "Utilizadores(as) convidados(as) apenas", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "inviteForMe": "Convite para mim", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "inviteText": "{username} convidou-te para o FluffyChat.\n1. Instala o FluffyChat: https://fluffychat.im\n2. Regista-te ou inicia sessão.\n3. Abre a ligação de convite: {link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "isTyping": "está a escrever…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "joinedTheChat": "{username} entrou na conversa", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "joinRoom": "Entrar na sala", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "kicked": "{username} expulsou {targetName}", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickedAndBanned": "{username} expulsou e baniu {targetName}", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickFromChat": "Expulsar da conversa", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "lastActiveAgo": "Ativo(a) pela última vez: {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "leave": "Sair", + "@leave": { + "type": "text", + "placeholders": {} + }, + "leftTheChat": "Saiu da conversa", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "license": "Licença", + "@license": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "Claro", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "loadCountMoreParticipants": "Carregar mais {count} participantes", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "loadingPleaseWait": "A carregar... Por favor aguarde.", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "loadMore": "Carregar mais…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "locationDisabledNotice": "Os serviços de localização estão desativados. Por favor, ativa-os para poder partilhar a sua localização.", + "@locationDisabledNotice": { + "type": "text", + "placeholders": {} + }, + "locationPermissionDeniedNotice": "Permissão de localização recusada. Por favor, concede permissão para poderes partilhar a tua posição.", + "@locationPermissionDeniedNotice": { + "type": "text", + "placeholders": {} + }, + "login": "Entrar", + "@login": { + "type": "text", + "placeholders": {} + }, + "logInTo": "Entrar em {homeserver}", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "logout": "Sair", + "@logout": { + "type": "text", + "placeholders": {} + }, + "memberChanges": "Alterações de membros", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "mention": "Mencionar", + "@mention": { + "type": "text", + "placeholders": {} + }, + "messages": "Mensagens", + "@messages": { + "type": "text", + "placeholders": {} + }, + "moderator": "Moderador", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "muteChat": "Silenciar conversa", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "Por favor,", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "newChat": "Nova conversa", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "Nova mensagem no FluffyChat", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "newVerificationRequest": "Novo pedido de verificação!", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "next": "Próximo", + "@next": { + "type": "text", + "placeholders": {} + }, + "no": "Não", + "@no": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "Nenhuma ligação ao servidor", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "noEmotesFound": "Nenhuns emotes encontrados. 😕", + "@noEmotesFound": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "Só podes ativar a encriptação quando a sala não for publicamente acessível.", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "noGoogleServicesWarning": "Parece que não tens nenhuns serviços da Google no seu telemóvel. É uma boa decisão para a sua privacidade! Para receber notificações instantâneas no FluffyChat, recomendamos que uses https://microg.org/ ou https://unifiedpush.org/.", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "noMatrixServer": "{server1} não é um servidor Matrix, usar {server2}?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "none": "Nenhum", + "@none": { + "type": "text", + "placeholders": {} + }, + "changedTheChatAvatar": "{username} alterou o avatar da conversa", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibilityTo": "{username} alterou a visibilidade do histórico para: {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheChatDescriptionTo": "{username} alterou a descrição da conversa para: '{description}'", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "changedTheChatNameTo": "{username} alterou o nome da conversa para: '{chatname}'", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changedTheGuestAccessRules": "{username} alterou as regras de acesso de visitantes", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibility": "{username} alterou a visibilidade do histórico", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sendAMessage": "Enviar a mensagem", + "@sendAMessage": { + "type": "text", + "placeholders": {} + }, + "sendAudio": "Enviar áudio", + "@sendAudio": { + "type": "text", + "placeholders": {} + }, + "sendAsText": "Enviar como texto", + "@sendAsText": { + "type": "text" + }, + "send": "Enviar", + "@send": { + "type": "text", + "placeholders": {} + }, + "appLock": "Bloqueio da aplicação", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "Ainda não adicionaste uma forma de recuperar a tua palavra-passe.", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "noPermission": "Sem permissão", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "Não foram encontradas nenhumas salas…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "notifications": "Notificações", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "notificationsEnabledForThisAccount": "Notificações ativadas para esta conta", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "numUsersTyping": "Estão {count} utilizadores(as) a escrever…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "obtainingLocation": "A obter localização…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "offensive": "Offensivo", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "offline": "Offline", + "@offline": { + "type": "text", + "placeholders": {} + }, + "ok": "ok", + "@ok": { + "type": "text", + "placeholders": {} + }, + "online": "Online", + "@online": { + "type": "text", + "placeholders": {} + }, + "onlineKeyBackupEnabled": "A cópia de segurança online de chaves está ativada", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "Ups! Infelizmente, ocorreu um erro ao configurar as notificações instantâneas.", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "Ups, algo correu mal…", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "Abrir aplicação para ler mensagens", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "openCamera": "Abrir câmara", + "@openCamera": { + "type": "text", + "placeholders": {} + }, + "oneClientLoggedOut": "Um dos teus clientes terminou sessão", + "@oneClientLoggedOut": {}, + "addAccount": "Adicionar conta", + "@addAccount": {}, + "editBundlesForAccount": "Editar pacotes para esta conta", + "@editBundlesForAccount": {}, + "addToBundle": "Adicionar ao pacote", + "@addToBundle": {}, + "removeFromBundle": "Remover deste pacote", + "@removeFromBundle": {}, + "bundleName": "Nome do pacote", + "@bundleName": {}, + "enableMultiAccounts": "(BETA) Ativar múltiplas contas neste dispositivo", + "@enableMultiAccounts": {}, + "openInMaps": "Abrir nos mapas", + "@openInMaps": { + "type": "text", + "placeholders": {} + }, + "link": "Ligação", + "@link": {}, + "serverRequiresEmail": "Este servidor precisa de validar o teu endereço de correio eletrónico para o registo.", + "@serverRequiresEmail": {}, + "or": "Ou", + "@or": { + "type": "text", + "placeholders": {} + }, + "participant": "Participante", + "@participant": { + "type": "text", + "placeholders": {} + }, + "passphraseOrKey": "senha ou chave de recuperação", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "password": "Palavra-passe", + "@password": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "Palavra-passe esquecida", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "A palavra-passe foi alterada", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "passwordRecovery": "Recuperação de palavra-passe", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "people": "Pessoas", + "@people": { + "type": "text", + "placeholders": {} + }, + "pickImage": "Escolher uma imagem", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "pin": "Afixar", + "@pin": { + "type": "text", + "placeholders": {} + }, + "play": "Reproduzir {fileName}", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "pleaseChoose": "Por favor, escolhe", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "pleaseChooseAPasscode": "Por favor, escolhe um código-passe", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pleaseClickOnLink": "Por favor, clica na ligação no correio eletrónico e depois continua.", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "Por favor, insere 4 dígitos ou deixa vazio para desativar o bloqueio da aplicação.", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "Por favor, insere a tua palavra-passe", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "Por favor, insere o teu código", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "Por favor, insere o teu nome de utilizador", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "pleaseFollowInstructionsOnWeb": "Por favor, segue as instruções no website e clica em \"Seguinte\".", + "@pleaseFollowInstructionsOnWeb": { + "type": "text", + "placeholders": {} + }, + "privacy": "Privacidade", + "@privacy": { + "type": "text", + "placeholders": {} + }, + "publicRooms": "Salas públicas", + "@publicRooms": { + "type": "text", + "placeholders": {} + }, + "reason": "Razão", + "@reason": { + "type": "text", + "placeholders": {} + }, + "redactedAnEvent": "{username} eliminou um evento", + "@redactedAnEvent": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "recording": "A gravar", + "@recording": { + "type": "text", + "placeholders": {} + }, + "redactMessage": "Eliminar mensagem", + "@redactMessage": { + "type": "text", + "placeholders": {} + }, + "register": "Registar", + "@register": { + "type": "text", + "placeholders": {} + }, + "reject": "Rejeitar", + "@reject": { + "type": "text", + "placeholders": {} + }, + "rejectedTheInvitation": "{username} rejeitou o convite", + "@rejectedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "rejoin": "Reentrar", + "@rejoin": { + "type": "text", + "placeholders": {} + }, + "remove": "Remover", + "@remove": { + "type": "text", + "placeholders": {} + }, + "removeAllOtherDevices": "Remover todos os outros dispositivos", + "@removeAllOtherDevices": { + "type": "text", + "placeholders": {} + }, + "removedBy": "Removido por {username}", + "@removedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removeDevice": "Remover dispositivo", + "@removeDevice": { + "type": "text", + "placeholders": {} + }, + "unbanFromChat": "Perdoar nesta conversa", + "@unbanFromChat": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "Remover o teu avatar", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "renderRichContent": "Exibir conteúdo de mensagem rico", + "@renderRichContent": { + "type": "text", + "placeholders": {} + }, + "replaceRoomWithNewerVersion": "Substituir sala com versão mais recente", + "@replaceRoomWithNewerVersion": { + "type": "text", + "placeholders": {} + }, + "reply": "Responder", + "@reply": { + "type": "text", + "placeholders": {} + }, + "reportMessage": "Reportar mensagem", + "@reportMessage": { + "type": "text", + "placeholders": {} + }, + "requestPermission": "Pedir permissão", + "@requestPermission": { + "type": "text", + "placeholders": {} + }, + "roomHasBeenUpgraded": "A sala foi atualizada", + "@roomHasBeenUpgraded": { + "type": "text", + "placeholders": {} + }, + "roomVersion": "Versão da sala", + "@roomVersion": { + "type": "text", + "placeholders": {} + }, + "saveFile": "Guardar ficheiro", + "@saveFile": { + "type": "text", + "placeholders": {} + }, + "search": "Procurar", + "@search": { + "type": "text", + "placeholders": {} + }, + "security": "Segurança", + "@security": { + "type": "text", + "placeholders": {} + }, + "seenByUser": "Visto por {username}", + "@seenByUser": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sendFile": "Enviar ficheiro", + "@sendFile": { + "type": "text", + "placeholders": {} + }, + "sendImage": "Enviar imagem", + "@sendImage": { + "type": "text", + "placeholders": {} + }, + "sendMessages": "Enviar mensagens", + "@sendMessages": { + "type": "text", + "placeholders": {} + }, + "sendOriginal": "Enviar original", + "@sendOriginal": { + "type": "text", + "placeholders": {} + }, + "sendSticker": "Enviar autocolante", + "@sendSticker": { + "type": "text", + "placeholders": {} + }, + "sendVideo": "Enviar vídeo", + "@sendVideo": { + "type": "text", + "placeholders": {} + }, + "sentAFile": "{username} enviar um ficheiro", + "@sentAFile": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAnAudio": "{username} enviar um áudio", + "@sentAnAudio": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAPicture": "{username} enviar uma imagem", + "@sentAPicture": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentASticker": "{username} enviou um autocolante", + "@sentASticker": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAVideo": "{username} enviou um vídeo", + "@sentAVideo": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "commandHint_clearcache": "Limpar cache", + "@commandHint_clearcache": { + "type": "text", + "description": "Usage hint for the command /clearcache" + }, + "commandHint_create": "Criar uma conversa de grupo vazia\nUsa --no-encryption para desativar a encriptação", + "@commandHint_create": { + "type": "text", + "description": "Usage hint for the command /create" + }, + "commandHint_discardsession": "Descartar sessão", + "@commandHint_discardsession": { + "type": "text", + "description": "Usage hint for the command /discardsession" + }, + "commandHint_dm": "Iniciar uma conversa direta\nUsa --no-encryption para desativar a encriptação", + "@commandHint_dm": { + "type": "text", + "description": "Usage hint for the command /dm" + }, + "dehydrate": "Exportar sessão e limpar dispositivo", + "@dehydrate": {}, + "dehydrateWarning": "Esta ação não pode ser revertida. Assegura-te que guardas bem a cópia de segurança.", + "@dehydrateWarning": {}, + "hydrateTorLong": "Exportaste a tua sessão na última vez que estiveste no TOR? Importa-a rapidamente e continua a conversar.", + "@hydrateTorLong": {}, + "dehydrateTor": "Utilizadores do TOR: Exportar sessão", + "@dehydrateTor": {}, + "hydrate": "Restaurar a partir de cópia de segurança", + "@hydrate": {}, + "hydrateTor": "Utilizadores do TOR: Importar sessão", + "@hydrateTor": {}, + "dehydrateTorLong": "Para utilizadores do TOR, é recomendado exportar a sessão antes de fechar a janela.", + "@dehydrateTorLong": {} +} diff --git a/assets/l10n/intl_ro.arb b/assets/l10n/intl_ro.arb index 00b17e74c..4715436e7 100644 --- a/assets/l10n/intl_ro.arb +++ b/assets/l10n/intl_ro.arb @@ -1,2376 +1,2303 @@ { - "@@last_modified": "2021-08-14 12:41:09.918296", - "about": "Despre", - "@about": { - "type": "text", - "placeholders": {} - }, - "accept": "Accept", - "@accept": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "{username} a aceptat invitați", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "Cont", - "@account": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "{username} a activat criptarea end-to-end", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "admin": "Administrator", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "poreclă", - "@alias": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "{senderName} a acceptat apelul", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "Oricine se poate alătura", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "archive": "Arhivă", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "Vizitatorii \"guest\" se pot alătura", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "Ești sigur?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "Pentru a putea conecta cealaltă persoană, te rog introdu parola sau cheia ta de recuperare.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "Accepți cererea de verificare de la {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "banFromChat": "Interzis din conversație", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "Interzis", - "@banned": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "{username} a interzis pe {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "blockDevice": "Blochează dispozitiv", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "cancel": "Anulează", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "changeDeviceName": "Schimbă numele dispozitiv", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "{username} a schimbat poza conversați", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatDescriptionTo": "{username} a schimbat descrierea grupului în '{description}'", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheChatNameTo": "{username} a schimbat porecla în '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "commandHint_unban": "Dezinterziceți utilizatorul ales din această cameră", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "deviceId": "ID-ul Dispozitiv", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "Dispozitive", - "@devices": { - "type": "text", - "placeholders": {} - }, - "directChats": "Chaturi directe", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "{senderName} a terminat apelul", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "enterYourHomeserver": "Introduceți homeserverul vostru", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "groupWith": "Grup cu {displayname}", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "howOffensiveIsThisContent": "Cât de ofensiv este acest conținut?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "kickFromChat": "Dați afară din chat", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "rejoin": "Reintrați", - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "sentCallInformations": "{senderName} a trimis informație de apel", - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "showPassword": "Afișați parola", - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "no": "Nu", - "@no": { - "type": "text", - "placeholders": {} - }, - "sendMessages": "Trimiteți mesaje", - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "submit": "Trimiteți", - "@submit": { - "type": "text", - "placeholders": {} - }, - "unreadChats": "{unreadCount, plural, =1{Un chat necitit} other{{unreadCount} chaturi necitite}}", - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "verifySuccess": "A reușit verificarea!", - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "voiceMessage": "Mesaj vocal", - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "wallpaper": "Imagine de fundal", - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "reactedWith": "{sender} a reacționat cu {reaction}", - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "changePassword": "Schimbați parola", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "next": "Următor", - "@next": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "Fără conexiune la server", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "Nu ați adăugat încă nici un mod de recuperare pentru parola voastră.", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "notifications": "Notificări", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "openVideoCamera": "Deschideți camera pentru video", - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "Deschideți aplicația să citiți mesajele", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "openCamera": "Deschideți camera", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "removedBy": "Eliminat de {username}", - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removeDevice": "Eliminați dispozitivul", - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "share": "Partajați", - "@share": { - "type": "text", - "placeholders": {} - }, - "shareLocation": "Partajați locația", - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "skip": "Săriți peste", - "@skip": { - "type": "text", - "placeholders": {} - }, - "sourceCode": "Codul surs", - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "spaceIsPublic": "Spațiul este public", - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "spaceName": "Numele spațiului", - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "toggleFavorite": "Comutați favoritul", - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "unblockDevice": "Debloca dispozitiv", - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "unknownDevice": "Dispozitiv necunoscut", - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "verify": "Verificați", - "@verify": { - "type": "text", - "placeholders": {} - }, - "weSentYouAnEmail": "V-am trimis un email", - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "youAreNoLongerParticipatingInThisChat": "Nu mai participați în acest chat", - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "yourPublicKey": "Cheia voastră publică", - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "addToSpaceDescription": "Alegeți un spațiu în care să adăugați acest chat.", - "@addToSpaceDescription": {}, - "placeCall": "Faceți apel", - "@placeCall": {}, - "voiceCall": "Apel vocal", - "@voiceCall": {}, - "unsupportedAndroidVersion": "Versiune de Android nesuportat", - "@unsupportedAndroidVersion": {}, - "previousAccount": "Contul anterior", - "@previousAccount": {}, - "userIsTyping": "{username} tastează…", - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "widgetCustom": "Personalizat", - "@widgetCustom": {}, - "screenSharingTitle": "partajarea de ecran", - "@screenSharingTitle": {}, - "newGroup": "Grup nou", - "@newGroup": {}, - "changedTheRoomInvitationLink": "{username} a schimbat linkul de invitație", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "chat": "Chat", - "@chat": { - "type": "text", - "placeholders": {} - }, - "chats": "Chaturi", - "@chats": { - "type": "text", - "placeholders": {} - }, - "invited": "Invitat", - "@invited": { - "type": "text", - "placeholders": {} - }, - "login": "Conectați-vă", - "@login": { - "type": "text", - "placeholders": {} - }, - "online": "Online", - "@online": { - "type": "text", - "placeholders": {} - }, - "onlineKeyBackupEnabled": "Backup de cheie online este activat", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "removeFromBundle": "Stergeți din acest pachet", - "@removeFromBundle": {}, - "enableMultiAccounts": "(BETA) Activați multiple conturi pe acest dispozitiv", - "@enableMultiAccounts": {}, - "participant": "Participant", - "@participant": { - "type": "text", - "placeholders": {} - }, - "openInMaps": "Deschideți pe hartă", - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "Vă rugăm să introduceți pinul vostru", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "privacy": "Confidențialitate", - "@privacy": { - "type": "text", - "placeholders": {} - }, - "pushRules": "Regulile Push", - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "recording": "Înregistrare", - "@recording": { - "type": "text", - "placeholders": {} - }, - "register": "Înregistrați-vă", - "@register": { - "type": "text", - "placeholders": {} - }, - "redactMessage": "Redactați mesaj", - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "roomVersion": "Versiunea camerei", - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "security": "Securitate", - "@security": { - "type": "text", - "placeholders": {} - }, - "sendFile": "Trimiteți fișier", - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "setStatus": "Stabiliți status", - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "settings": "Configurări", - "@settings": { - "type": "text", - "placeholders": {} - }, - "inviteForMe": "Invitați pentru mine", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "hasWithdrawnTheInvitationFor": "{username} a retras invitația pentru {targetName}", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "help": "Ajutor", - "@help": { - "type": "text", - "placeholders": {} - }, - "unknownEncryptionAlgorithm": "Algoritm de criptare necunoscut", - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "unmuteChat": "Dezamuțați chat", - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "unpin": "Anulează fixarea", - "@unpin": { - "type": "text", - "placeholders": {} - }, - "unbannedUser": "{username} a ridicat interzicerea lui {targetName}", - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "openChat": "Deschideți Chat", - "@openChat": {}, - "emailOrUsername": "Email sau nume de utilizator", - "@emailOrUsername": {}, - "youBannedUser": "Ați interzis pe {user}", - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "fileIsTooBigForServer": "Serverul reportează că fișierul este prea mare să fie trimis.", - "@fileIsTooBigForServer": {}, - "widgetName": "Nume", - "@widgetName": {}, - "sorryThatsNotPossible": "Scuze... acest nu este posibil", - "@sorryThatsNotPossible": {}, - "enableEncryptionWarning": "Activând criptare, nu mai puteți să o dezactivați în viitor. Sunteți sigur?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "commandMissing": "{command} nu este o comandă.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "status": "Status", - "@status": { - "type": "text", - "placeholders": {} - }, - "connect": "Conectați", - "@connect": { - "type": "text", - "placeholders": {} - }, - "you": "Voi", - "@you": { - "type": "text", - "placeholders": {} - }, - "start": "Începeți", - "@start": {}, - "videoCallsBetaWarning": "Vă rugăm să luați notă că apeluri video sunt în beta. Se poate că nu funcționează normal sau de loc pe fie care platformă.", - "@videoCallsBetaWarning": {}, - "pinMessage": "Fixați în cameră", - "@pinMessage": {}, - "wasDirectChatDisplayName": "Chat gol (a fost {oldDisplayName})", - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "pleaseClickOnLink": "Vă rugăm să deschideți linkul din email și apoi să procedați.", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "reportUser": "Reportați utilizator", - "@reportUser": {}, - "encryptionNotEnabled": "Criptare nu e activată", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "publicRooms": "Camere Publice", - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "addToBundle": "Adăugați în pachet", - "@addToBundle": {}, - "theyDontMatch": "Nu sunt asemănători", - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "loadingPleaseWait": "Încărcând... Vă rugăm să așteptați.", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "dateWithoutYear": "{month}-{day}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "theyMatch": "Sunt asemănători", - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "title": "FluffyChat", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "toggleMuted": "Comutați amuțeștarea", - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "scanQrCode": "Scanați cod QR", - "@scanQrCode": {}, - "addAccount": "Adăugați cont", - "@addAccount": {}, - "experimentalVideoCalls": "Apeluri video experimentale", - "@experimentalVideoCalls": {}, - "confirmEventUnpin": "Sunteți sigur că doriți să anulați permanent fixarea evenimentului?", - "@confirmEventUnpin": {}, - "emojis": "Emoji-uri", - "@emojis": {}, - "switchToAccount": "Schimbați la contul {number}", - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "nextAccount": "Contul următor", - "@nextAccount": {}, - "indexedDbErrorTitle": "Probleme cu modul privat", - "@indexedDbErrorTitle": {}, - "users": "Utilizatori", - "@users": {}, - "startFirstChat": "Începeți primul chatul vostru", - "@startFirstChat": {}, - "callingPermissions": "Permisiuni de apel", - "@callingPermissions": {}, - "callingAccount": "Cont de apel", - "@callingAccount": {}, - "foregroundServiceRunning": "Această notificare apare când serviciul de foreground rulează.", - "@foregroundServiceRunning": {}, - "callingAccountDetails": "Permite FluffyChat să folosească aplicația de apeluri nativă android.", - "@callingAccountDetails": {}, - "appearOnTop": "Apare deasupra", - "@appearOnTop": {}, - "appearOnTopDetails": "Permite aplicația să apare deasupra (nu este necesar dacă aveți FluffyChat stabilit ca cont de apeluri)", - "@appearOnTopDetails": {}, - "currentlyActive": "Activ acum", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "Conține displayname", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "isTyping": "tastează…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "chatBackup": "Backup de chat", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "repeatPassword": "Repetați parola", - "@repeatPassword": {}, - "changeTheme": "Schimbați tema aplicației", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "Chatul a fost adăugat la acest spațiu", - "@chatHasBeenAddedToThisSpace": {}, - "clearArchive": "Ștergeți arhiva", - "@clearArchive": {}, - "commandHint_markasdm": "Marcați ca cameră de mesaje directe", - "@commandHint_markasdm": {}, - "commandHint_markasgroup": "Marcați ca grup", - "@commandHint_markasgroup": {}, - "commandHint_ban": "Interziceți acesul utilizatorului ales din această cameră", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_clearcache": "Ștergeți cache", - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "commandHint_create": "Creați un grup de chat gol\nFolosiți --no-encryption să dezactivați criptare", - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "commandHint_discardsession": "Renunțați sesiunea", - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "commandHint_kick": "Dați afară pe utilizatorul ales din această cameră", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_leave": "Renunțați la această cameră", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_myroomavatar": "Alegeți un avatar pentru această cameră (foloșește mxc-uri)", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_myroomnick": "Alegeți un displayname pentru această cameră", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_op": "Stabiliți nivelul de putere a utilizatorul ales (implicit: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_plain": "Trimiteți text simplu/neformatat", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_react": "Trimiteți răspuns ca reacție", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandHint_send": "Trimiteți text", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandInvalid": "Comandă nevalibilă", - "@commandInvalid": { - "type": "text" - }, - "compareEmojiMatch": "Vă rugăm să comparați emoji-urile", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Vă rugăm să comparați numerele", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Dezcriptarea mesajului a eșuat: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "create": "Creați", - "@create": { - "type": "text", - "placeholders": {} - }, - "createdTheChat": "💬{username} a creat chatul", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "createNewSpace": "Spațiu nou", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "dateWithYear": "{year}-{month}-{day}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "allRooms": "Toate chaturi de grup", - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "forward": "Înainte", - "@forward": { - "type": "text", - "placeholders": {} - }, - "groups": "Grupuri", - "@groups": { - "type": "text", - "placeholders": {} - }, - "hideRedactedEvents": "Ascunde evenimente redactate", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "Ascunde evenimente necunoscute", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "identity": "Identitate", - "@identity": { - "type": "text", - "placeholders": {} - }, - "ignore": "Ignorați", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "Utilizatori ignorați", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "Am făcut click pe link", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "incorrectPassphraseOrKey": "Parolă sau cheie de recuperare incorectă", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "Inofensiv", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "Invitați contact", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "Invitați contact la {groupName}", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "inviteText": "{username} v-a invitat la FluffyChat.\n1. Instalați FluffyChat: https://fluffychat.im\n2. Înregistrați-vă sau conectați-vă\n3. Deschideți invitația: {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "joinedTheChat": "👋{username} a intrat în chat", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "kicked": "👞{username} a dat afară pe {targetName}", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "lastActiveAgo": "Ultima dată activ: {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "leave": "Renunțați", - "@leave": { - "type": "text", - "placeholders": {} - }, - "leftTheChat": "A plecat din chat", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "license": "Permis", - "@license": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "Luminat", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "loadCountMoreParticipants": "Încărcați încă mai {count} participanți", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "dehydrate": "Exportați sesiunea și ștergeți dispozitivul", - "@dehydrate": {}, - "dehydrateTor": "Utilizatori de TOR: Exportați sesiunea", - "@dehydrateTor": {}, - "dehydrateTorLong": "Pentru utilizatori de TOR, este recomandat să exportați sesiunea înainte de a închideți fereastra.", - "@dehydrateTorLong": {}, - "hydrateTor": "Utilizatori TOR: Importați sesiune exportată", - "@hydrateTor": {}, - "hydrateTorLong": "Ați exportat sesiunea vostră ultima dată pe TOR? Importați-o repede și continuați să conversați.", - "@hydrateTorLong": {}, - "hydrate": "Restaurați din fișier backup", - "@hydrate": {}, - "loadMore": "Încarcă mai multe…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "logout": "Deconectați-vă", - "@logout": { - "type": "text", - "placeholders": {} - }, - "mention": "Menționați", - "@mention": { - "type": "text", - "placeholders": {} - }, - "messages": "Mesaje", - "@messages": { - "type": "text", - "placeholders": {} - }, - "moderator": "Moderator", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "noEmotesFound": "Nu s-a găsit nici un emote. 😕", - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "Criptare nu poate fi activată până când camera este accesibilă public.", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "none": "Niciunul", - "@none": { - "type": "text", - "placeholders": {} - }, - "noPermission": "Fără permisie", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "Nici o cameră nu s-a găsit…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "notificationsEnabledForThisAccount": "Notificări activate pentru acest cont", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "obtainingLocation": "Obținând locație…", - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "offline": "Offline", - "@offline": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "Ups, ceva a eșuat…", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "reject": "Respingeți", - "@reject": { - "type": "text", - "placeholders": {} - }, - "unbanFromChat": "Revoca interzicerea din chat", - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "roomHasBeenUpgraded": "Camera a fost actualizată", - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "setCustomEmotes": "Stabiliți emoji-uri personalizate", - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "setPermissionsLevel": "Stabiliți nivelul de permisii", - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "singlesignon": "Autentificare unică", - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "startedACall": "{senderName} a început un apel", - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "statusExampleMessage": "Ce faceți?", - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "tooManyRequestsWarning": "Prea multe cereri. Vă rugăm să încercați din nou mai tărziu!", - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "unknownEvent": "Evenimet necunoscut '{type}'", - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "verified": "Verificat", - "@verified": { - "type": "text", - "placeholders": {} - }, - "verifyStart": "Începeți verificare", - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "videoCall": "Apel video", - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "visibilityOfTheChatHistory": "Vizibilitatea istoria chatului", - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "visibleForAllParticipants": "Vizibil pentru toți participanți", - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerEmoji": "Așteptând pe partenerul să accepte emoji-ul…", - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerNumbers": "Așteptând pe partenerul să accepte numerele…", - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "warning": "Avertizment!", - "@warning": { - "type": "text", - "placeholders": {} - }, - "whoCanPerformWhichAction": "Cine poate face care acțiune", - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "whoIsAllowedToJoinThisGroup": "Cine se poate alătura la acest grup", - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "whyDoYouWantToReportThis": "De ce doriți să reportați acest conținut?", - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "wipeChatBackup": "Ștergeți backup-ul vostru de chat să creați o nouă cheie de recuperare?", - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "withTheseAddressesRecoveryDescription": "Cu acestea adrese puteți să vă recuperați parola.", - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "youHaveBeenBannedFromThisChat": "Ați fost interzis din acest chat", - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "messageInfo": "Info mesajului", - "@messageInfo": {}, - "time": "Timp", - "@time": {}, - "messageType": "Fel de mesaj", - "@messageType": {}, - "sender": "Trimițător", - "@sender": {}, - "openGallery": "Deschideți galeria", - "@openGallery": {}, - "removeFromSpace": "Eliminați din spațiu", - "@removeFromSpace": {}, - "publish": "Publicați", - "@publish": {}, - "videoWithSize": "Video ({size})", - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "unsupportedAndroidVersionLong": "Această funcție are nevoie de o versiune de Android mai nouă. Vă rugăm să verificați dacă sunt actualizări sau suport de la Lineage OS.", - "@unsupportedAndroidVersionLong": {}, - "dismiss": "Respingeți", - "@dismiss": {}, - "widgetVideo": "Video", - "@widgetVideo": {}, - "widgetEtherpad": "Notiță text", - "@widgetEtherpad": {}, - "widgetJitsi": "Jitsi Meet", - "@widgetJitsi": {}, - "widgetUrlError": "Acest URL nu este valibil.", - "@widgetUrlError": {}, - "widgetNameError": "Vă rugăm să introduceți un nume de afișare.", - "@widgetNameError": {}, - "errorAddingWidget": "Adăugarea widget-ului a eșuat.", - "@errorAddingWidget": {}, - "youRejectedTheInvitation": "Ați respins invitația", - "@youRejectedTheInvitation": {}, - "youJoinedTheChat": "Va-ți alăturat la chat", - "@youJoinedTheChat": {}, - "youAcceptedTheInvitation": "👍Ați acceptat invitația", - "@youAcceptedTheInvitation": {}, - "youHaveWithdrawnTheInvitationFor": "Ați retras invitația pentru {user}", - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "youInvitedBy": "📩Ați fost invitat de {user}", - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "unlockOldMessages": "Deblocați mesajele vechi", - "@unlockOldMessages": {}, - "youInvitedUser": "📩Ați invitat pe {user}", - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "youKicked": "👞Ați dat afară pe {user}", - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "youUnbannedUser": "Ați ridicat interzicerea lui {user}", - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "storeInAndroidKeystore": "Stoca în Android KeyStore", - "@storeInAndroidKeystore": {}, - "user": "Utilizator", - "@user": {}, - "custom": "Personalizat", - "@custom": {}, - "screenSharingDetail": "Partajați ecranul în FluffyChat", - "@screenSharingDetail": {}, - "storeSecurlyOnThisDevice": "Stoca sigur pe acest dispozitiv", - "@storeSecurlyOnThisDevice": {}, - "otherCallingPermissions": "Microfon, cameră și alte permisiuni lui FluffyChat", - "@otherCallingPermissions": {}, - "whyIsThisMessageEncrypted": "De ce este acest mesaj ilizibil?", - "@whyIsThisMessageEncrypted": {}, - "newSpace": "Spațiu nou", - "@newSpace": {}, - "enterSpace": "Intrați în spațiu", - "@enterSpace": {}, - "enterRoom": "Intrați în cameră", - "@enterRoom": {}, - "allSpaces": "Toate spațiile", - "@allSpaces": {}, - "numChats": "{number} chaturi", - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "hideUnimportantStateEvents": "Ascundeți evenimente de stare neimportante", - "@hideUnimportantStateEvents": {}, - "doNotShowAgain": "Nu se mai apară din nou", - "@doNotShowAgain": {}, - "newSpaceDescription": "Spațiile vă permit să vă consolidați chaturile și să stabiliți comunități private sau publice.", - "@newSpaceDescription": {}, - "encryptThisChat": "Criptați acest chat", - "@encryptThisChat": {}, - "disableEncryptionWarning": "Pentru motive de securitate, nu este posibil să dezactivați criptarea unui chat în care criptare este activată.", - "@disableEncryptionWarning": {}, - "noBackupWarning": "Avertisment! Fără să activați backup de chat, veți pierde accesul la mesajele voastre criptate. E foarte recomandat să activați backup de chat înainte să vă deconectați.", - "@noBackupWarning": {}, - "noOtherDevicesFound": "Nu s-a găsit alte dispozitive", - "@noOtherDevicesFound": {}, - "fileHasBeenSavedAt": "Fișierul a fost salvat la {path}", - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "jump": "Săriți", - "@jump": {}, - "report": "reportați", - "@report": {}, - "jumpToLastReadMessage": "Săriți la ultimul citit mesaj", - "@jumpToLastReadMessage": {}, - "memberChanges": "Schimbări de membri", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "Musafiri pot să se alăture", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "fileName": "Nume de fișier", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "fontSize": "Mărimea fontului", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "fromJoining": "De la alăturare", - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "fromTheInvitation": "De la invitația", - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "goToTheNewRoom": "Mergeți la camera nouă", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "group": "Grup", - "@group": { - "type": "text", - "placeholders": {} - }, - "groupIsPublic": "Grupul este public", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "guestsAreForbidden": "Musafiri sunt interziși", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "kickedAndBanned": "🙅{username} a dat afară și a interzis pe {targetName} din cameră", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "dehydrateWarning": "Această actiune nu poate fi anulată. Asigurați-vă că păstrați fișierul backup.", - "@dehydrateWarning": {}, - "joinRoom": "Alăturați la cameră", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "logInTo": "Conectați-vă la {homeserver}", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "locationDisabledNotice": "Servicile de locație sunt dezactivate. Vă rugăm să le activați să împărțiți locația voastră.", - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "noGoogleServicesWarning": "Se pare că nu aveți serviciile google pe dispozitivul vostru. Această decizie este bună pentru confidențialitatea voastră! Să primiți notificari push în FluffyChat vă recomandăm https://microg.org/ sau https://unifiedpush.org/.", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "noMatrixServer": "{server1} nu este server matrix, înlocuiți cu {server2}?", - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "numUsersTyping": "{count} utilizatori tastează…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "offensive": "Ofensiv", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "confirm": "Confirmați", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "or": "Sau", - "@or": { - "type": "text", - "placeholders": {} - }, - "serverRequiresEmail": "Acest server trebuie să valideze emailul vostru pentru înregistrare.", - "@serverRequiresEmail": {}, - "waitingPartnerAcceptRequest": "Așteptând pe partenerul să accepte cererea…", - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "Întunecat", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "sharedTheLocation": "{username} sa partajat locația", - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "setInvitationLink": "Stabiliți linkul de invitație", - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "transferFromAnotherDevice": "Transfera de la alt dispozitiv", - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "synchronizingPleaseWait": "Sincronizează... Vă rugăm să așteptați.", - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "systemTheme": "Sistem", - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "toggleUnread": "Marcați Citit/Necitit", - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "tryToSendAgain": "Încercați să trimiteți din nou", - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "unavailable": "Nedisponibil", - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "userAndUserAreTyping": "{username} și {username2} tastează…", - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "userLeftTheChat": "🚪{username} a plecat din chat", - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "userAndOthersAreTyping": "{username} și {count} alți tastează…", - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "userSentUnknownEvent": "{username} a trimis un eveniment {type}", - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "unverified": "Neverificat", - "@unverified": {}, - "verifyTitle": "Verificând celălalt cont", - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "visibleForEveryone": "Vizibil pentru toți", - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "readUpToHere": "Citit până aici", - "@readUpToHere": {}, - "changedTheHistoryVisibility": "{username} a schimbat vizibilitatea istoriei chatului", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "copy": "Copiați", - "@copy": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "Displayname a fost schimbat", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "invitedUsersOnly": "Numai utilizatori invitați", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "configureChat": "Configurați chat", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "Copiat în clipboard", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "device": "Dispozitiv", - "@device": { - "type": "text", - "placeholders": {} - }, - "username": "Nume de utilizator", - "@username": { - "type": "text", - "placeholders": {} - }, - "sentAnAudio": "🎤{username} a trimis audio", - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAFile": "📁{username} a trimis un fișier", - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "indexedDbErrorLong": "Stocarea de mesaje nu este activat implicit în modul privat.\nVă rugăm să vizitați\n- about:config\n- stabiliți dom.indexedDB.privateBrowsing.enabled la true\nAstfel, nu este posibil să folosiți FluffyChat.", - "@indexedDbErrorLong": {}, - "addWidget": "Adăugați widget", - "@addWidget": {}, - "locationPermissionDeniedNotice": "Permisiunea locației blocată. Vă rugăm să o dezblocați să împărțiți locația voastră.", - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "newChat": "Chat nou", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "💬 Mesaj nou în FluffyChat", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "sentAPicture": "🖼️ {username} a trimis o poză", - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAVideo": "🎥{username} a trimis un video", - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentASticker": "😊 {username} a trimis un sticker", - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "storeInSecureStorageDescription": "Păstrați cheia de recuperare în stocarea sigură a acestui dispozitiv.", - "@storeInSecureStorageDescription": {}, - "saveKeyManuallyDescription": "Activați dialogul de partajare sistemului sau folosiți clipboard-ul să salvați manual această cheie.", - "@saveKeyManuallyDescription": {}, - "countFiles": "{count} fișiere", - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "hugContent": "{senderName} vă îmbrățișează", - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "storeInAppleKeyChain": "Stoca în Apple KeyChain", - "@storeInAppleKeyChain": {}, - "addEmail": "Adăugați email", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "confirmMatrixId": "Vă rugăm să confirmați Matrix ID-ul vostru să ștergeți contul vostru.", - "@confirmMatrixId": {}, - "cuddleContent": "{senderName} vă îmbrățișează", - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "supposedMxid": "ID-ul ar trebuii să fie {mxid}", - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "commandHint_html": "Trimiteți text format ca HTML", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "addToSpace": "Adăugați la spațiu", - "@addToSpace": {}, - "commandHint_hug": "Trimiteți o îmbrățișare", - "@commandHint_hug": {}, - "badServerVersionsException": "Homeserver-ul suportă versiunele de Spec următoare:\n{serverVersions}\nDar această aplicație suportă numai {supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "badServerLoginTypesException": "Homeserver-ul suportă următoarele feluri de login:\n{serverVersions}\nDar această aplicație suportă numai:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} a schimbat regulile pentru acesul musafirilor la: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRulesTo": "{username} a schimbat regulile de alăturare la: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "yourChatBackupHasBeenSetUp": "Backup-ul vostru de chat a fost configurat.", - "@yourChatBackupHasBeenSetUp": {}, - "cantOpenUri": "Nu se poate deschide URI-ul {uri}", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "changedTheDisplaynameTo": "{username} s-a schimbat displayname la: '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRules": "{username} a schimbat regulile pentru acesul musafirilor", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changeTheHomeserver": "Schimbați homeserver-ul", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "Mesajele voastre vechi sunt sigurate cu o cheie de recuperare. Vă rugăm să nu o pierdeți.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "Conținutul a fost reportat la administratori serverului", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "Detalii de chat", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "commandHint_dm": "Porniți un chat direct\nFolosiți --no-encryption să dezactivați criptare", - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "commandHint_me": "Descrieți-vă", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "contactHasBeenInvitedToTheGroup": "Contactul a fost invitat la grup", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "Conține nume de utilizator", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "Copiați în clipboard", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "countParticipants": "{count} participanți", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "delete": "Ștergeți", - "@delete": { - "type": "text", - "placeholders": {} - }, - "deactivateAccountWarning": "Această acțiune va dezactiva contul vostru. Nu poate fi anulat! Sunteți sigur?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "Ștergeți contul", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "Nivel de permisiuni implicită", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "Ștergeți mesajul", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "Descărcați fișierul", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "Activați pachet de emote global", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "everythingReady": "Totul e gata!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "Editați servere blocate", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "Shortcode de emote nevalibil!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "edit": "Editați", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "Schimbați pseudonimele camerei", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "Chat gol", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "Activați criptare", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "encrypted": "Criptat", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "Schimbați displayname", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "Schimbați avatarul din cameră", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Emote deja există!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "Pachete de emoturi din cameră", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Configurări Emote", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "emoteShortcode": "Shortcode de emote", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Trebuie să alegeți shortcode pentru emote și o imagine!", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "encryption": "Criptare", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "enterAnEmailAddress": "Introduceți o adresă email", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "homeserver": "Homeserver", - "@homeserver": {}, - "errorObtainingLocation": "Obținerea locației a eșuat: {error}", - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "ok": "Ok", - "@ok": { - "type": "text", - "placeholders": {} - }, - "youKickedAndBanned": "🙅Ați dat afară și interzis pe {user}", - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "noKeyForThisMessage": "Această chestie poate să se întâmple când mesajul a fost trimis înainte să vă conectați contul cu acest dispozitiv.\n\nO altă explicație ar fi dacă trimițătorul a blocat dispozitivul vostru sau ceva s-a întâmplat cu conexiunea la internet\n\nPuteți să citiți mesajul în o altă seșiune? Atunci puteți să transferați mesajul de acolo! Mergeți la Configurări > Dispozitive și verificați că dispozitivele s-au verificat. Când deschideți camera în viitor și ambele seșiune sunt în foreground, cheile va fi transmise automat. \n\nDoriți să îți păstrați cheile când deconectați sau schimbați dispozitive? Fiți atenți să activați backup de chat în configurări.", - "@noKeyForThisMessage": {}, - "sendAsText": "Trimiteți ca text", - "@sendAsText": { - "type": "text" - }, - "reportErrorDescription": "Ceva a eșuat. Vă rugăm să încercați din nou mai tărziu. Dacă doriți, puteți să reportați problema la dezvoltatori.", - "@reportErrorDescription": {}, - "openLinkInBrowser": "Deschideți linkul în browser", - "@openLinkInBrowser": {}, - "send": "Trimiteți", - "@send": { - "type": "text", - "placeholders": {} - }, - "sendAMessage": "Trimiteți un mesaj", - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "sendAudio": "Trimiteți audio", - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "sendOriginal": "Trimiteți original", - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "sendVideo": "Trimiteți video", - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "sendImage": "Trimiteți imagine", - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "sendSticker": "Trimiteți sticker", - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterRecoveryKeyDescription": "Să vă deblocați mesajele vechi, vă rugăm să introduceți cheia de recuperare creată de o seșiune anterioră. Cheia de recuperare NU este parola voastră.", - "@pleaseEnterRecoveryKeyDescription": {}, - "separateChatTypes": "Afișați chaturi directe și grupuri separat", - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "setAsCanonicalAlias": "Stabiliți ca pseudonimul primar", - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "writeAMessage": "Scrieți un mesaj…", - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "yes": "Da", - "@yes": { - "type": "text", - "placeholders": {} - }, - "markAsRead": "Marcați ca citit", - "@markAsRead": {}, - "oopsPushError": "Ups! Din păcate, o eroare s-a întâmplat cu stabilirea de notificări push.", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "oneClientLoggedOut": "Unul dintre clienților voștri a fost deconectat", - "@oneClientLoggedOut": {}, - "editBundlesForAccount": "Editați pachetele pentru acest cont", - "@editBundlesForAccount": {}, - "bundleName": "Numele pachetului", - "@bundleName": {}, - "link": "Link", - "@link": {}, - "passphraseOrKey": "frază de acces sau cheie de recuperare", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "password": "Parolă", - "@password": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "Parola uitată", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "Parola a fost schimbată", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "passwordRecovery": "Recuperare parolei", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "people": "Persoane", - "@people": { - "type": "text", - "placeholders": {} - }, - "pickImage": "Alegeți o imagine", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "pleaseChoose": "Vă rugăm să alegeți", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "pin": "Fixați", - "@pin": { - "type": "text", - "placeholders": {} - }, - "pleaseChooseAPasscode": "Vă rugăm să alegeți un passcode", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "Vă rugăm să introduceți 4 cifre sau puteți să lăsați gol să dezactivați lacătul aplicației.", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "Vă rugăm să introduceți parola voastră", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "Vă rugăm să introduceți username-ul vostru", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "pleaseFollowInstructionsOnWeb": "Vă rugăm să urmați instrucțiunele pe website și apoi să apăsați pe următor.", - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "reason": "Motiv", - "@reason": { - "type": "text", - "placeholders": {} - }, - "rejectedTheInvitation": "{username} a respins invitația", - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "redactedAnEvent": "{username} a redactat un eveniment", - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removeAllOtherDevices": "Eliminați toate celelalte dispozitive", - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "removeYourAvatar": "Ștergeți avatarul", - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "renderRichContent": "Reda conținut bogat al mesajelor", - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "replaceRoomWithNewerVersion": "Înlocuiți camera cu versiune mai nouă", - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "reply": "Răspundeți", - "@reply": { - "type": "text", - "placeholders": {} - }, - "reportMessage": "Raportați mesajul", - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "requestPermission": "Cereți permisiune", - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "saveFile": "Salvați fișierul", - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "search": "Căutați", - "@search": { - "type": "text", - "placeholders": {} - }, - "recoveryKey": "Cheie de recuperare", - "@recoveryKey": {}, - "recoveryKeyLost": "Cheia de recuperare pierdută?", - "@recoveryKeyLost": {}, - "seenByUser": "Văzut de {username}", - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "muteChat": "Amuțați chatul", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "Vă rugăm să fiți conștienți că e nevoie de Pantalaimon să folosiți criptare end-to-end deocamdată.", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "autoplayImages": "Anima automatic stickere și emote animate", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "sendOnEnter": "Trimite cu tasta enter", - "@sendOnEnter": {}, - "changedTheChatPermissions": "{username} a schimbat permisiunile chatului", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "extremeOffensive": "De foarte mare ofensă", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "id": "ID", - "@id": { - "type": "text", - "placeholders": {} - }, - "invitedUser": "📩{username} a invitat {targetName}", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "deviceKeys": "Cheile dispozitivului:", - "@deviceKeys": {}, - "pleaseEnterRecoveryKey": "Vă rugăm să introduceți cheia voastră de recuperare:", - "@pleaseEnterRecoveryKey": {}, - "newVerificationRequest": "Cerere de verificare nouă!", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "remove": "Eliminați", - "@remove": { - "type": "text", - "placeholders": {} - }, - "play": "Redați {fileName}", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "channelCorruptedDecryptError": "Criptarea a fost corupată", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "Alegeți o parolă robustă", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "commandHint_cuddle": "Trimiteți o îmbrățișare", - "@commandHint_cuddle": {}, - "googlyEyesContent": "{senderName} v-a trimis ochi googly", - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "areYouSureYouWantToLogout": "Sunteți sigur că doriți să vă deconectați?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "changedTheRoomAliases": "{username} a schimbat pseudonimele camerei", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changeYourAvatar": "Schimbați avatarul vostru", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "commandHint_join": "Alăturați-vă la camera alesă", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "allChats": "Toate Chaturile", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "commandHint_invite": "Invitați utilizatorul ales la această cameră", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "changeTheNameOfTheGroup": "Schimbați numele grupului", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "commandHint_googly": "Trimiteți câțiva ochi googly", - "@commandHint_googly": {}, - "botMessages": "Mesaje Bot", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "all": "Toate", - "@all": { - "type": "text", - "placeholders": {} - }, - "blocked": "Blocat", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "changedTheJoinRules": "{username} a schimbat regulile de alăturare", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheProfileAvatar": "{username} s-a schimbat avatarul", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "appLock": "Lacăt aplicație", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "changedTheHistoryVisibilityTo": "{username} a schimbat vizibilitatea istoriei chatului la: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "close": "Închideți", - "@close": { - "type": "text", - "placeholders": {} - }, - "reopenChat": "Deschide din nou chatul", - "@reopenChat": {}, - "pleaseTryAgainLaterOrChooseDifferentServer": "Vă rugăm să încercați din nou mai târziu sau să alegeți un server diferit.", - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "signInWithPassword": "Conectați-vă cu parolă", - "@signInWithPassword": {}, - "@setColorTheme": {}, - "@banUserDescription": {}, - "@removeDevicesDescription": {}, - "@tryAgain": {}, - "@unbanUserDescription": {}, - "@messagesStyle": {}, - "@chatDescription": {}, - "@pushNotificationsNotAvailable": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@makeAdminDescription": {}, - "@setChatDescription": {}, - "@importFromZipFile": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@optionalRedactReason": {}, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@redactMessageDescription": {}, - "@invalidInput": {}, - "@addChatDescription": {}, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@invitePrivateChat": {}, - "@importEmojis": {}, - "@noChatDescriptionYet": {}, - "@learnMore": {}, - "@notAnImage": {}, - "@chatDescriptionHasBeenChanged": {}, - "@roomUpgradeDescription": {}, - "@pleaseEnterANumber": {}, - "@profileNotFound": {}, - "@shareInviteLink": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@replace": {}, - "@createGroup": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@invite": {} -} \ No newline at end of file + "@@last_modified": "2021-08-14 12:41:09.918296", + "about": "Despre", + "@about": { + "type": "text", + "placeholders": {} + }, + "accept": "Accept", + "@accept": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "{username} a aceptat invitați", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "account": "Cont", + "@account": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "{username} a activat criptarea end-to-end", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "admin": "Administrator", + "@admin": { + "type": "text", + "placeholders": {} + }, + "alias": "poreclă", + "@alias": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "{senderName} a acceptat apelul", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "anyoneCanJoin": "Oricine se poate alătura", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "archive": "Arhivă", + "@archive": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "Vizitatorii \"guest\" se pot alătura", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "Ești sigur?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "askSSSSSign": "Pentru a putea conecta cealaltă persoană, te rog introdu parola sau cheia ta de recuperare.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "Accepți cererea de verificare de la {username}?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "banFromChat": "Interzis din conversație", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "banned": "Interzis", + "@banned": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "{username} a interzis pe {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "blockDevice": "Blochează dispozitiv", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "cancel": "Anulează", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "changeDeviceName": "Schimbă numele dispozitiv", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "changedTheChatAvatar": "{username} a schimbat poza conversați", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatDescriptionTo": "{username} a schimbat descrierea grupului în '{description}'", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "changedTheChatNameTo": "{username} a schimbat porecla în '{chatname}'", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "commandHint_unban": "Dezinterziceți utilizatorul ales din această cameră", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "deviceId": "ID-ul Dispozitiv", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "devices": "Dispozitive", + "@devices": { + "type": "text", + "placeholders": {} + }, + "directChats": "Chaturi directe", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "{senderName} a terminat apelul", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "enterYourHomeserver": "Introduceți homeserverul vostru", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "groupWith": "Grup cu {displayname}", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "howOffensiveIsThisContent": "Cât de ofensiv este acest conținut?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "kickFromChat": "Dați afară din chat", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "rejoin": "Reintrați", + "@rejoin": { + "type": "text", + "placeholders": {} + }, + "sentCallInformations": "{senderName} a trimis informație de apel", + "@sentCallInformations": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "showPassword": "Afișați parola", + "@showPassword": { + "type": "text", + "placeholders": {} + }, + "no": "Nu", + "@no": { + "type": "text", + "placeholders": {} + }, + "sendMessages": "Trimiteți mesaje", + "@sendMessages": { + "type": "text", + "placeholders": {} + }, + "submit": "Trimiteți", + "@submit": { + "type": "text", + "placeholders": {} + }, + "unreadChats": "{unreadCount, plural, =1{Un chat necitit} other{{unreadCount} chaturi necitite}}", + "@unreadChats": { + "type": "text", + "placeholders": { + "unreadCount": {} + } + }, + "verifySuccess": "A reușit verificarea!", + "@verifySuccess": { + "type": "text", + "placeholders": {} + }, + "voiceMessage": "Mesaj vocal", + "@voiceMessage": { + "type": "text", + "placeholders": {} + }, + "wallpaper": "Imagine de fundal", + "@wallpaper": { + "type": "text", + "placeholders": {} + }, + "reactedWith": "{sender} a reacționat cu {reaction}", + "@reactedWith": { + "type": "text", + "placeholders": { + "sender": {}, + "reaction": {} + } + }, + "changePassword": "Schimbați parola", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "next": "Următor", + "@next": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "Fără conexiune la server", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "Nu ați adăugat încă nici un mod de recuperare pentru parola voastră.", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "notifications": "Notificări", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "openVideoCamera": "Deschideți camera pentru video", + "@openVideoCamera": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "Deschideți aplicația să citiți mesajele", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "openCamera": "Deschideți camera", + "@openCamera": { + "type": "text", + "placeholders": {} + }, + "removedBy": "Eliminat de {username}", + "@removedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removeDevice": "Eliminați dispozitivul", + "@removeDevice": { + "type": "text", + "placeholders": {} + }, + "share": "Partajați", + "@share": { + "type": "text", + "placeholders": {} + }, + "shareLocation": "Partajați locația", + "@shareLocation": { + "type": "text", + "placeholders": {} + }, + "skip": "Săriți peste", + "@skip": { + "type": "text", + "placeholders": {} + }, + "sourceCode": "Codul surs", + "@sourceCode": { + "type": "text", + "placeholders": {} + }, + "spaceIsPublic": "Spațiul este public", + "@spaceIsPublic": { + "type": "text", + "placeholders": {} + }, + "spaceName": "Numele spațiului", + "@spaceName": { + "type": "text", + "placeholders": {} + }, + "toggleFavorite": "Comutați favoritul", + "@toggleFavorite": { + "type": "text", + "placeholders": {} + }, + "unblockDevice": "Debloca dispozitiv", + "@unblockDevice": { + "type": "text", + "placeholders": {} + }, + "unknownDevice": "Dispozitiv necunoscut", + "@unknownDevice": { + "type": "text", + "placeholders": {} + }, + "verify": "Verificați", + "@verify": { + "type": "text", + "placeholders": {} + }, + "weSentYouAnEmail": "V-am trimis un email", + "@weSentYouAnEmail": { + "type": "text", + "placeholders": {} + }, + "youAreNoLongerParticipatingInThisChat": "Nu mai participați în acest chat", + "@youAreNoLongerParticipatingInThisChat": { + "type": "text", + "placeholders": {} + }, + "yourPublicKey": "Cheia voastră publică", + "@yourPublicKey": { + "type": "text", + "placeholders": {} + }, + "addToSpaceDescription": "Alegeți un spațiu în care să adăugați acest chat.", + "@addToSpaceDescription": {}, + "placeCall": "Faceți apel", + "@placeCall": {}, + "voiceCall": "Apel vocal", + "@voiceCall": {}, + "unsupportedAndroidVersion": "Versiune de Android nesuportat", + "@unsupportedAndroidVersion": {}, + "previousAccount": "Contul anterior", + "@previousAccount": {}, + "userIsTyping": "{username} tastează…", + "@userIsTyping": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "widgetCustom": "Personalizat", + "@widgetCustom": {}, + "screenSharingTitle": "partajarea de ecran", + "@screenSharingTitle": {}, + "newGroup": "Grup nou", + "@newGroup": {}, + "changedTheRoomInvitationLink": "{username} a schimbat linkul de invitație", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "chat": "Chat", + "@chat": { + "type": "text", + "placeholders": {} + }, + "chats": "Chaturi", + "@chats": { + "type": "text", + "placeholders": {} + }, + "invited": "Invitat", + "@invited": { + "type": "text", + "placeholders": {} + }, + "login": "Conectați-vă", + "@login": { + "type": "text", + "placeholders": {} + }, + "online": "Online", + "@online": { + "type": "text", + "placeholders": {} + }, + "onlineKeyBackupEnabled": "Backup de cheie online este activat", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "removeFromBundle": "Stergeți din acest pachet", + "@removeFromBundle": {}, + "enableMultiAccounts": "(BETA) Activați multiple conturi pe acest dispozitiv", + "@enableMultiAccounts": {}, + "participant": "Participant", + "@participant": { + "type": "text", + "placeholders": {} + }, + "openInMaps": "Deschideți pe hartă", + "@openInMaps": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "Vă rugăm să introduceți pinul vostru", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "privacy": "Confidențialitate", + "@privacy": { + "type": "text", + "placeholders": {} + }, + "pushRules": "Regulile Push", + "@pushRules": { + "type": "text", + "placeholders": {} + }, + "recording": "Înregistrare", + "@recording": { + "type": "text", + "placeholders": {} + }, + "register": "Înregistrați-vă", + "@register": { + "type": "text", + "placeholders": {} + }, + "redactMessage": "Redactați mesaj", + "@redactMessage": { + "type": "text", + "placeholders": {} + }, + "roomVersion": "Versiunea camerei", + "@roomVersion": { + "type": "text", + "placeholders": {} + }, + "security": "Securitate", + "@security": { + "type": "text", + "placeholders": {} + }, + "sendFile": "Trimiteți fișier", + "@sendFile": { + "type": "text", + "placeholders": {} + }, + "setStatus": "Stabiliți status", + "@setStatus": { + "type": "text", + "placeholders": {} + }, + "settings": "Configurări", + "@settings": { + "type": "text", + "placeholders": {} + }, + "inviteForMe": "Invitați pentru mine", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "hasWithdrawnTheInvitationFor": "{username} a retras invitația pentru {targetName}", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "help": "Ajutor", + "@help": { + "type": "text", + "placeholders": {} + }, + "unknownEncryptionAlgorithm": "Algoritm de criptare necunoscut", + "@unknownEncryptionAlgorithm": { + "type": "text", + "placeholders": {} + }, + "unmuteChat": "Dezamuțați chat", + "@unmuteChat": { + "type": "text", + "placeholders": {} + }, + "unpin": "Anulează fixarea", + "@unpin": { + "type": "text", + "placeholders": {} + }, + "unbannedUser": "{username} a ridicat interzicerea lui {targetName}", + "@unbannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "openChat": "Deschideți Chat", + "@openChat": {}, + "emailOrUsername": "Email sau nume de utilizator", + "@emailOrUsername": {}, + "youBannedUser": "Ați interzis pe {user}", + "@youBannedUser": { + "placeholders": { + "user": {} + } + }, + "fileIsTooBigForServer": "Serverul reportează că fișierul este prea mare să fie trimis.", + "@fileIsTooBigForServer": {}, + "widgetName": "Nume", + "@widgetName": {}, + "sorryThatsNotPossible": "Scuze... acest nu este posibil", + "@sorryThatsNotPossible": {}, + "enableEncryptionWarning": "Activând criptare, nu mai puteți să o dezactivați în viitor. Sunteți sigur?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "commandMissing": "{command} nu este o comandă.", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "status": "Status", + "@status": { + "type": "text", + "placeholders": {} + }, + "connect": "Conectați", + "@connect": { + "type": "text", + "placeholders": {} + }, + "you": "Voi", + "@you": { + "type": "text", + "placeholders": {} + }, + "start": "Începeți", + "@start": {}, + "videoCallsBetaWarning": "Vă rugăm să luați notă că apeluri video sunt în beta. Se poate că nu funcționează normal sau de loc pe fie care platformă.", + "@videoCallsBetaWarning": {}, + "pinMessage": "Fixați în cameră", + "@pinMessage": {}, + "wasDirectChatDisplayName": "Chat gol (a fost {oldDisplayName})", + "@wasDirectChatDisplayName": { + "type": "text", + "placeholders": { + "oldDisplayName": {} + } + }, + "pleaseClickOnLink": "Vă rugăm să deschideți linkul din email și apoi să procedați.", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "reportUser": "Reportați utilizator", + "@reportUser": {}, + "encryptionNotEnabled": "Criptare nu e activată", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "publicRooms": "Camere Publice", + "@publicRooms": { + "type": "text", + "placeholders": {} + }, + "addToBundle": "Adăugați în pachet", + "@addToBundle": {}, + "theyDontMatch": "Nu sunt asemănători", + "@theyDontMatch": { + "type": "text", + "placeholders": {} + }, + "loadingPleaseWait": "Încărcând... Vă rugăm să așteptați.", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "dateWithoutYear": "{month}-{day}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "theyMatch": "Sunt asemănători", + "@theyMatch": { + "type": "text", + "placeholders": {} + }, + "title": "FluffyChat", + "@title": { + "description": "Title for the application", + "type": "text", + "placeholders": {} + }, + "toggleMuted": "Comutați amuțeștarea", + "@toggleMuted": { + "type": "text", + "placeholders": {} + }, + "scanQrCode": "Scanați cod QR", + "@scanQrCode": {}, + "addAccount": "Adăugați cont", + "@addAccount": {}, + "experimentalVideoCalls": "Apeluri video experimentale", + "@experimentalVideoCalls": {}, + "confirmEventUnpin": "Sunteți sigur că doriți să anulați permanent fixarea evenimentului?", + "@confirmEventUnpin": {}, + "emojis": "Emoji-uri", + "@emojis": {}, + "switchToAccount": "Schimbați la contul {number}", + "@switchToAccount": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "nextAccount": "Contul următor", + "@nextAccount": {}, + "indexedDbErrorTitle": "Probleme cu modul privat", + "@indexedDbErrorTitle": {}, + "users": "Utilizatori", + "@users": {}, + "startFirstChat": "Începeți primul chatul vostru", + "@startFirstChat": {}, + "callingPermissions": "Permisiuni de apel", + "@callingPermissions": {}, + "callingAccount": "Cont de apel", + "@callingAccount": {}, + "foregroundServiceRunning": "Această notificare apare când serviciul de foreground rulează.", + "@foregroundServiceRunning": {}, + "callingAccountDetails": "Permite FluffyChat să folosească aplicația de apeluri nativă android.", + "@callingAccountDetails": {}, + "appearOnTop": "Apare deasupra", + "@appearOnTop": {}, + "appearOnTopDetails": "Permite aplicația să apare deasupra (nu este necesar dacă aveți FluffyChat stabilit ca cont de apeluri)", + "@appearOnTopDetails": {}, + "currentlyActive": "Activ acum", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "Conține displayname", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "isTyping": "tastează…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "chatBackup": "Backup de chat", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "repeatPassword": "Repetați parola", + "@repeatPassword": {}, + "changeTheme": "Schimbați tema aplicației", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "chatHasBeenAddedToThisSpace": "Chatul a fost adăugat la acest spațiu", + "@chatHasBeenAddedToThisSpace": {}, + "clearArchive": "Ștergeți arhiva", + "@clearArchive": {}, + "commandHint_markasdm": "Marcați ca cameră de mesaje directe", + "@commandHint_markasdm": {}, + "commandHint_markasgroup": "Marcați ca grup", + "@commandHint_markasgroup": {}, + "commandHint_ban": "Interziceți acesul utilizatorului ales din această cameră", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_clearcache": "Ștergeți cache", + "@commandHint_clearcache": { + "type": "text", + "description": "Usage hint for the command /clearcache" + }, + "commandHint_create": "Creați un grup de chat gol\nFolosiți --no-encryption să dezactivați criptare", + "@commandHint_create": { + "type": "text", + "description": "Usage hint for the command /create" + }, + "commandHint_discardsession": "Renunțați sesiunea", + "@commandHint_discardsession": { + "type": "text", + "description": "Usage hint for the command /discardsession" + }, + "commandHint_kick": "Dați afară pe utilizatorul ales din această cameră", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_leave": "Renunțați la această cameră", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_myroomavatar": "Alegeți un avatar pentru această cameră (foloșește mxc-uri)", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_myroomnick": "Alegeți un displayname pentru această cameră", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "commandHint_op": "Stabiliți nivelul de putere a utilizatorul ales (implicit: 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_plain": "Trimiteți text simplu/neformatat", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_react": "Trimiteți răspuns ca reacție", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "commandHint_send": "Trimiteți text", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "commandInvalid": "Comandă nevalibilă", + "@commandInvalid": { + "type": "text" + }, + "compareEmojiMatch": "Vă rugăm să comparați emoji-urile", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "Vă rugăm să comparați numerele", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "Dezcriptarea mesajului a eșuat: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "create": "Creați", + "@create": { + "type": "text", + "placeholders": {} + }, + "createdTheChat": "💬{username} a creat chatul", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "createNewSpace": "Spațiu nou", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "dateWithYear": "{year}-{month}-{day}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "allRooms": "Toate chaturi de grup", + "@allRooms": { + "type": "text", + "placeholders": {} + }, + "forward": "Înainte", + "@forward": { + "type": "text", + "placeholders": {} + }, + "groups": "Grupuri", + "@groups": { + "type": "text", + "placeholders": {} + }, + "hideRedactedEvents": "Ascunde evenimente redactate", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "Ascunde evenimente necunoscute", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "identity": "Identitate", + "@identity": { + "type": "text", + "placeholders": {} + }, + "ignore": "Ignorați", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "Utilizatori ignorați", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "Am făcut click pe link", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "incorrectPassphraseOrKey": "Parolă sau cheie de recuperare incorectă", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "Inofensiv", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "Invitați contact", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "Invitați contact la {groupName}", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "inviteText": "{username} v-a invitat la FluffyChat.\n1. Instalați FluffyChat: https://fluffychat.im\n2. Înregistrați-vă sau conectați-vă\n3. Deschideți invitația: {link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "joinedTheChat": "👋{username} a intrat în chat", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "kicked": "👞{username} a dat afară pe {targetName}", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "lastActiveAgo": "Ultima dată activ: {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "leave": "Renunțați", + "@leave": { + "type": "text", + "placeholders": {} + }, + "leftTheChat": "A plecat din chat", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "license": "Permis", + "@license": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "Luminat", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "loadCountMoreParticipants": "Încărcați încă mai {count} participanți", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "dehydrate": "Exportați sesiunea și ștergeți dispozitivul", + "@dehydrate": {}, + "dehydrateTor": "Utilizatori de TOR: Exportați sesiunea", + "@dehydrateTor": {}, + "dehydrateTorLong": "Pentru utilizatori de TOR, este recomandat să exportați sesiunea înainte de a închideți fereastra.", + "@dehydrateTorLong": {}, + "hydrateTor": "Utilizatori TOR: Importați sesiune exportată", + "@hydrateTor": {}, + "hydrateTorLong": "Ați exportat sesiunea vostră ultima dată pe TOR? Importați-o repede și continuați să conversați.", + "@hydrateTorLong": {}, + "hydrate": "Restaurați din fișier backup", + "@hydrate": {}, + "loadMore": "Încarcă mai multe…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "logout": "Deconectați-vă", + "@logout": { + "type": "text", + "placeholders": {} + }, + "mention": "Menționați", + "@mention": { + "type": "text", + "placeholders": {} + }, + "messages": "Mesaje", + "@messages": { + "type": "text", + "placeholders": {} + }, + "moderator": "Moderator", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "noEmotesFound": "Nu s-a găsit nici un emote. 😕", + "@noEmotesFound": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "Criptare nu poate fi activată până când camera este accesibilă public.", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "none": "Niciunul", + "@none": { + "type": "text", + "placeholders": {} + }, + "noPermission": "Fără permisie", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "Nici o cameră nu s-a găsit…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "notificationsEnabledForThisAccount": "Notificări activate pentru acest cont", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "obtainingLocation": "Obținând locație…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "offline": "Offline", + "@offline": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "Ups, ceva a eșuat…", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "reject": "Respingeți", + "@reject": { + "type": "text", + "placeholders": {} + }, + "unbanFromChat": "Revoca interzicerea din chat", + "@unbanFromChat": { + "type": "text", + "placeholders": {} + }, + "roomHasBeenUpgraded": "Camera a fost actualizată", + "@roomHasBeenUpgraded": { + "type": "text", + "placeholders": {} + }, + "setCustomEmotes": "Stabiliți emoji-uri personalizate", + "@setCustomEmotes": { + "type": "text", + "placeholders": {} + }, + "setPermissionsLevel": "Stabiliți nivelul de permisii", + "@setPermissionsLevel": { + "type": "text", + "placeholders": {} + }, + "singlesignon": "Autentificare unică", + "@singlesignon": { + "type": "text", + "placeholders": {} + }, + "startedACall": "{senderName} a început un apel", + "@startedACall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "statusExampleMessage": "Ce faceți?", + "@statusExampleMessage": { + "type": "text", + "placeholders": {} + }, + "tooManyRequestsWarning": "Prea multe cereri. Vă rugăm să încercați din nou mai tărziu!", + "@tooManyRequestsWarning": { + "type": "text", + "placeholders": {} + }, + "unknownEvent": "Evenimet necunoscut '{type}'", + "@unknownEvent": { + "type": "text", + "placeholders": { + "type": {} + } + }, + "verified": "Verificat", + "@verified": { + "type": "text", + "placeholders": {} + }, + "verifyStart": "Începeți verificare", + "@verifyStart": { + "type": "text", + "placeholders": {} + }, + "videoCall": "Apel video", + "@videoCall": { + "type": "text", + "placeholders": {} + }, + "visibilityOfTheChatHistory": "Vizibilitatea istoria chatului", + "@visibilityOfTheChatHistory": { + "type": "text", + "placeholders": {} + }, + "visibleForAllParticipants": "Vizibil pentru toți participanți", + "@visibleForAllParticipants": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerEmoji": "Așteptând pe partenerul să accepte emoji-ul…", + "@waitingPartnerEmoji": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerNumbers": "Așteptând pe partenerul să accepte numerele…", + "@waitingPartnerNumbers": { + "type": "text", + "placeholders": {} + }, + "warning": "Avertizment!", + "@warning": { + "type": "text", + "placeholders": {} + }, + "whoCanPerformWhichAction": "Cine poate face care acțiune", + "@whoCanPerformWhichAction": { + "type": "text", + "placeholders": {} + }, + "whoIsAllowedToJoinThisGroup": "Cine se poate alătura la acest grup", + "@whoIsAllowedToJoinThisGroup": { + "type": "text", + "placeholders": {} + }, + "whyDoYouWantToReportThis": "De ce doriți să reportați acest conținut?", + "@whyDoYouWantToReportThis": { + "type": "text", + "placeholders": {} + }, + "wipeChatBackup": "Ștergeți backup-ul vostru de chat să creați o nouă cheie de recuperare?", + "@wipeChatBackup": { + "type": "text", + "placeholders": {} + }, + "withTheseAddressesRecoveryDescription": "Cu acestea adrese puteți să vă recuperați parola.", + "@withTheseAddressesRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "youHaveBeenBannedFromThisChat": "Ați fost interzis din acest chat", + "@youHaveBeenBannedFromThisChat": { + "type": "text", + "placeholders": {} + }, + "messageInfo": "Info mesajului", + "@messageInfo": {}, + "time": "Timp", + "@time": {}, + "messageType": "Fel de mesaj", + "@messageType": {}, + "sender": "Trimițător", + "@sender": {}, + "openGallery": "Deschideți galeria", + "@openGallery": {}, + "removeFromSpace": "Eliminați din spațiu", + "@removeFromSpace": {}, + "publish": "Publicați", + "@publish": {}, + "videoWithSize": "Video ({size})", + "@videoWithSize": { + "type": "text", + "placeholders": { + "size": {} + } + }, + "unsupportedAndroidVersionLong": "Această funcție are nevoie de o versiune de Android mai nouă. Vă rugăm să verificați dacă sunt actualizări sau suport de la Lineage OS.", + "@unsupportedAndroidVersionLong": {}, + "dismiss": "Respingeți", + "@dismiss": {}, + "widgetVideo": "Video", + "@widgetVideo": {}, + "widgetEtherpad": "Notiță text", + "@widgetEtherpad": {}, + "widgetJitsi": "Jitsi Meet", + "@widgetJitsi": {}, + "widgetUrlError": "Acest URL nu este valibil.", + "@widgetUrlError": {}, + "widgetNameError": "Vă rugăm să introduceți un nume de afișare.", + "@widgetNameError": {}, + "errorAddingWidget": "Adăugarea widget-ului a eșuat.", + "@errorAddingWidget": {}, + "youRejectedTheInvitation": "Ați respins invitația", + "@youRejectedTheInvitation": {}, + "youJoinedTheChat": "Va-ți alăturat la chat", + "@youJoinedTheChat": {}, + "youAcceptedTheInvitation": "👍Ați acceptat invitația", + "@youAcceptedTheInvitation": {}, + "youHaveWithdrawnTheInvitationFor": "Ați retras invitația pentru {user}", + "@youHaveWithdrawnTheInvitationFor": { + "placeholders": { + "user": {} + } + }, + "youInvitedBy": "📩Ați fost invitat de {user}", + "@youInvitedBy": { + "placeholders": { + "user": {} + } + }, + "unlockOldMessages": "Deblocați mesajele vechi", + "@unlockOldMessages": {}, + "youInvitedUser": "📩Ați invitat pe {user}", + "@youInvitedUser": { + "placeholders": { + "user": {} + } + }, + "youKicked": "👞Ați dat afară pe {user}", + "@youKicked": { + "placeholders": { + "user": {} + } + }, + "youUnbannedUser": "Ați ridicat interzicerea lui {user}", + "@youUnbannedUser": { + "placeholders": { + "user": {} + } + }, + "storeInAndroidKeystore": "Stoca în Android KeyStore", + "@storeInAndroidKeystore": {}, + "user": "Utilizator", + "@user": {}, + "custom": "Personalizat", + "@custom": {}, + "screenSharingDetail": "Partajați ecranul în FluffyChat", + "@screenSharingDetail": {}, + "storeSecurlyOnThisDevice": "Stoca sigur pe acest dispozitiv", + "@storeSecurlyOnThisDevice": {}, + "otherCallingPermissions": "Microfon, cameră și alte permisiuni lui FluffyChat", + "@otherCallingPermissions": {}, + "whyIsThisMessageEncrypted": "De ce este acest mesaj ilizibil?", + "@whyIsThisMessageEncrypted": {}, + "newSpace": "Spațiu nou", + "@newSpace": {}, + "enterSpace": "Intrați în spațiu", + "@enterSpace": {}, + "enterRoom": "Intrați în cameră", + "@enterRoom": {}, + "allSpaces": "Toate spațiile", + "@allSpaces": {}, + "numChats": "{number} chaturi", + "@numChats": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "hideUnimportantStateEvents": "Ascundeți evenimente de stare neimportante", + "@hideUnimportantStateEvents": {}, + "doNotShowAgain": "Nu se mai apară din nou", + "@doNotShowAgain": {}, + "newSpaceDescription": "Spațiile vă permit să vă consolidați chaturile și să stabiliți comunități private sau publice.", + "@newSpaceDescription": {}, + "encryptThisChat": "Criptați acest chat", + "@encryptThisChat": {}, + "disableEncryptionWarning": "Pentru motive de securitate, nu este posibil să dezactivați criptarea unui chat în care criptare este activată.", + "@disableEncryptionWarning": {}, + "noBackupWarning": "Avertisment! Fără să activați backup de chat, veți pierde accesul la mesajele voastre criptate. E foarte recomandat să activați backup de chat înainte să vă deconectați.", + "@noBackupWarning": {}, + "noOtherDevicesFound": "Nu s-a găsit alte dispozitive", + "@noOtherDevicesFound": {}, + "fileHasBeenSavedAt": "Fișierul a fost salvat la {path}", + "@fileHasBeenSavedAt": { + "type": "text", + "placeholders": { + "path": {} + } + }, + "jump": "Săriți", + "@jump": {}, + "report": "reportați", + "@report": {}, + "jumpToLastReadMessage": "Săriți la ultimul citit mesaj", + "@jumpToLastReadMessage": {}, + "memberChanges": "Schimbări de membri", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "Musafiri pot să se alăture", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "fileName": "Nume de fișier", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "fontSize": "Mărimea fontului", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "fromJoining": "De la alăturare", + "@fromJoining": { + "type": "text", + "placeholders": {} + }, + "fromTheInvitation": "De la invitația", + "@fromTheInvitation": { + "type": "text", + "placeholders": {} + }, + "goToTheNewRoom": "Mergeți la camera nouă", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "group": "Grup", + "@group": { + "type": "text", + "placeholders": {} + }, + "groupIsPublic": "Grupul este public", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "guestsAreForbidden": "Musafiri sunt interziși", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "kickedAndBanned": "🙅{username} a dat afară și a interzis pe {targetName} din cameră", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "dehydrateWarning": "Această actiune nu poate fi anulată. Asigurați-vă că păstrați fișierul backup.", + "@dehydrateWarning": {}, + "joinRoom": "Alăturați la cameră", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "logInTo": "Conectați-vă la {homeserver}", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "locationDisabledNotice": "Servicile de locație sunt dezactivate. Vă rugăm să le activați să împărțiți locația voastră.", + "@locationDisabledNotice": { + "type": "text", + "placeholders": {} + }, + "noGoogleServicesWarning": "Se pare că nu aveți serviciile google pe dispozitivul vostru. Această decizie este bună pentru confidențialitatea voastră! Să primiți notificari push în FluffyChat vă recomandăm https://microg.org/ sau https://unifiedpush.org/.", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "noMatrixServer": "{server1} nu este server matrix, înlocuiți cu {server2}?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "numUsersTyping": "{count} utilizatori tastează…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "offensive": "Ofensiv", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "confirm": "Confirmați", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "or": "Sau", + "@or": { + "type": "text", + "placeholders": {} + }, + "serverRequiresEmail": "Acest server trebuie să valideze emailul vostru pentru înregistrare.", + "@serverRequiresEmail": {}, + "waitingPartnerAcceptRequest": "Așteptând pe partenerul să accepte cererea…", + "@waitingPartnerAcceptRequest": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "Întunecat", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "sharedTheLocation": "{username} sa partajat locația", + "@sharedTheLocation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "setInvitationLink": "Stabiliți linkul de invitație", + "@setInvitationLink": { + "type": "text", + "placeholders": {} + }, + "transferFromAnotherDevice": "Transfera de la alt dispozitiv", + "@transferFromAnotherDevice": { + "type": "text", + "placeholders": {} + }, + "synchronizingPleaseWait": "Sincronizează... Vă rugăm să așteptați.", + "@synchronizingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "systemTheme": "Sistem", + "@systemTheme": { + "type": "text", + "placeholders": {} + }, + "toggleUnread": "Marcați Citit/Necitit", + "@toggleUnread": { + "type": "text", + "placeholders": {} + }, + "tryToSendAgain": "Încercați să trimiteți din nou", + "@tryToSendAgain": { + "type": "text", + "placeholders": {} + }, + "unavailable": "Nedisponibil", + "@unavailable": { + "type": "text", + "placeholders": {} + }, + "userAndUserAreTyping": "{username} și {username2} tastează…", + "@userAndUserAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "username2": {} + } + }, + "userLeftTheChat": "🚪{username} a plecat din chat", + "@userLeftTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "userAndOthersAreTyping": "{username} și {count} alți tastează…", + "@userAndOthersAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "count": {} + } + }, + "userSentUnknownEvent": "{username} a trimis un eveniment {type}", + "@userSentUnknownEvent": { + "type": "text", + "placeholders": { + "username": {}, + "type": {} + } + }, + "unverified": "Neverificat", + "@unverified": {}, + "verifyTitle": "Verificând celălalt cont", + "@verifyTitle": { + "type": "text", + "placeholders": {} + }, + "visibleForEveryone": "Vizibil pentru toți", + "@visibleForEveryone": { + "type": "text", + "placeholders": {} + }, + "readUpToHere": "Citit până aici", + "@readUpToHere": {}, + "changedTheHistoryVisibility": "{username} a schimbat vizibilitatea istoriei chatului", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "copy": "Copiați", + "@copy": { + "type": "text", + "placeholders": {} + }, + "displaynameHasBeenChanged": "Displayname a fost schimbat", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "invitedUsersOnly": "Numai utilizatori invitați", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "configureChat": "Configurați chat", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "Copiat în clipboard", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "device": "Dispozitiv", + "@device": { + "type": "text", + "placeholders": {} + }, + "username": "Nume de utilizator", + "@username": { + "type": "text", + "placeholders": {} + }, + "sentAnAudio": "🎤{username} a trimis audio", + "@sentAnAudio": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAFile": "📁{username} a trimis un fișier", + "@sentAFile": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "indexedDbErrorLong": "Stocarea de mesaje nu este activat implicit în modul privat.\nVă rugăm să vizitați\n- about:config\n- stabiliți dom.indexedDB.privateBrowsing.enabled la true\nAstfel, nu este posibil să folosiți FluffyChat.", + "@indexedDbErrorLong": {}, + "addWidget": "Adăugați widget", + "@addWidget": {}, + "locationPermissionDeniedNotice": "Permisiunea locației blocată. Vă rugăm să o dezblocați să împărțiți locația voastră.", + "@locationPermissionDeniedNotice": { + "type": "text", + "placeholders": {} + }, + "newChat": "Chat nou", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "💬 Mesaj nou în FluffyChat", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "sentAPicture": "🖼️ {username} a trimis o poză", + "@sentAPicture": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAVideo": "🎥{username} a trimis un video", + "@sentAVideo": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentASticker": "😊 {username} a trimis un sticker", + "@sentASticker": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "storeInSecureStorageDescription": "Păstrați cheia de recuperare în stocarea sigură a acestui dispozitiv.", + "@storeInSecureStorageDescription": {}, + "saveKeyManuallyDescription": "Activați dialogul de partajare sistemului sau folosiți clipboard-ul să salvați manual această cheie.", + "@saveKeyManuallyDescription": {}, + "countFiles": "{count} fișiere", + "@countFiles": { + "placeholders": { + "count": {} + } + }, + "hugContent": "{senderName} vă îmbrățișează", + "@hugContent": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "storeInAppleKeyChain": "Stoca în Apple KeyChain", + "@storeInAppleKeyChain": {}, + "addEmail": "Adăugați email", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "confirmMatrixId": "Vă rugăm să confirmați Matrix ID-ul vostru să ștergeți contul vostru.", + "@confirmMatrixId": {}, + "cuddleContent": "{senderName} vă îmbrățișează", + "@cuddleContent": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "supposedMxid": "ID-ul ar trebuii să fie {mxid}", + "@supposedMxid": { + "type": "text", + "placeholders": { + "mxid": {} + } + }, + "commandHint_html": "Trimiteți text format ca HTML", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "addToSpace": "Adăugați la spațiu", + "@addToSpace": {}, + "commandHint_hug": "Trimiteți o îmbrățișare", + "@commandHint_hug": {}, + "badServerVersionsException": "Homeserver-ul suportă versiunele de Spec următoare:\n{serverVersions}\nDar această aplicație suportă numai {supportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "badServerLoginTypesException": "Homeserver-ul suportă următoarele feluri de login:\n{serverVersions}\nDar această aplicație suportă numai:\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "changedTheGuestAccessRulesTo": "{username} a schimbat regulile pentru acesul musafirilor la: {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRulesTo": "{username} a schimbat regulile de alăturare la: {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "yourChatBackupHasBeenSetUp": "Backup-ul vostru de chat a fost configurat.", + "@yourChatBackupHasBeenSetUp": {}, + "cantOpenUri": "Nu se poate deschide URI-ul {uri}", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "changedTheDisplaynameTo": "{username} s-a schimbat displayname la: '{displayname}'", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRules": "{username} a schimbat regulile pentru acesul musafirilor", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changeTheHomeserver": "Schimbați homeserver-ul", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "chatBackupDescription": "Mesajele voastre vechi sunt sigurate cu o cheie de recuperare. Vă rugăm să nu o pierdeți.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "Conținutul a fost reportat la administratori serverului", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "chatDetails": "Detalii de chat", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "commandHint_dm": "Porniți un chat direct\nFolosiți --no-encryption să dezactivați criptare", + "@commandHint_dm": { + "type": "text", + "description": "Usage hint for the command /dm" + }, + "commandHint_me": "Descrieți-vă", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "contactHasBeenInvitedToTheGroup": "Contactul a fost invitat la grup", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "containsUserName": "Conține nume de utilizator", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "Copiați în clipboard", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "countParticipants": "{count} participanți", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "delete": "Ștergeți", + "@delete": { + "type": "text", + "placeholders": {} + }, + "deactivateAccountWarning": "Această acțiune va dezactiva contul vostru. Nu poate fi anulat! Sunteți sigur?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "Ștergeți contul", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "Nivel de permisiuni implicită", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "Ștergeți mesajul", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "Descărcați fișierul", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "enableEmotesGlobally": "Activați pachet de emote global", + "@enableEmotesGlobally": { + "type": "text", + "placeholders": {} + }, + "everythingReady": "Totul e gata!", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "Editați servere blocate", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "emoteInvalid": "Shortcode de emote nevalibil!", + "@emoteInvalid": { + "type": "text", + "placeholders": {} + }, + "edit": "Editați", + "@edit": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "Schimbați pseudonimele camerei", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "emptyChat": "Chat gol", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "Activați criptare", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "encrypted": "Criptat", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "Schimbați displayname", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "Schimbați avatarul din cameră", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "Emote deja există!", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "emotePacks": "Pachete de emoturi din cameră", + "@emotePacks": { + "type": "text", + "placeholders": {} + }, + "emoteSettings": "Configurări Emote", + "@emoteSettings": { + "type": "text", + "placeholders": {} + }, + "emoteShortcode": "Shortcode de emote", + "@emoteShortcode": { + "type": "text", + "placeholders": {} + }, + "emoteWarnNeedToPick": "Trebuie să alegeți shortcode pentru emote și o imagine!", + "@emoteWarnNeedToPick": { + "type": "text", + "placeholders": {} + }, + "encryption": "Criptare", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "enterAnEmailAddress": "Introduceți o adresă email", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "homeserver": "Homeserver", + "@homeserver": {}, + "errorObtainingLocation": "Obținerea locației a eșuat: {error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "ok": "Ok", + "@ok": { + "type": "text", + "placeholders": {} + }, + "youKickedAndBanned": "🙅Ați dat afară și interzis pe {user}", + "@youKickedAndBanned": { + "placeholders": { + "user": {} + } + }, + "noKeyForThisMessage": "Această chestie poate să se întâmple când mesajul a fost trimis înainte să vă conectați contul cu acest dispozitiv.\n\nO altă explicație ar fi dacă trimițătorul a blocat dispozitivul vostru sau ceva s-a întâmplat cu conexiunea la internet\n\nPuteți să citiți mesajul în o altă seșiune? Atunci puteți să transferați mesajul de acolo! Mergeți la Configurări > Dispozitive și verificați că dispozitivele s-au verificat. Când deschideți camera în viitor și ambele seșiune sunt în foreground, cheile va fi transmise automat. \n\nDoriți să îți păstrați cheile când deconectați sau schimbați dispozitive? Fiți atenți să activați backup de chat în configurări.", + "@noKeyForThisMessage": {}, + "sendAsText": "Trimiteți ca text", + "@sendAsText": { + "type": "text" + }, + "reportErrorDescription": "Ceva a eșuat. Vă rugăm să încercați din nou mai tărziu. Dacă doriți, puteți să reportați problema la dezvoltatori.", + "@reportErrorDescription": {}, + "openLinkInBrowser": "Deschideți linkul în browser", + "@openLinkInBrowser": {}, + "send": "Trimiteți", + "@send": { + "type": "text", + "placeholders": {} + }, + "sendAMessage": "Trimiteți un mesaj", + "@sendAMessage": { + "type": "text", + "placeholders": {} + }, + "sendAudio": "Trimiteți audio", + "@sendAudio": { + "type": "text", + "placeholders": {} + }, + "sendOriginal": "Trimiteți original", + "@sendOriginal": { + "type": "text", + "placeholders": {} + }, + "sendVideo": "Trimiteți video", + "@sendVideo": { + "type": "text", + "placeholders": {} + }, + "sendImage": "Trimiteți imagine", + "@sendImage": { + "type": "text", + "placeholders": {} + }, + "sendSticker": "Trimiteți sticker", + "@sendSticker": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterRecoveryKeyDescription": "Să vă deblocați mesajele vechi, vă rugăm să introduceți cheia de recuperare creată de o seșiune anterioră. Cheia de recuperare NU este parola voastră.", + "@pleaseEnterRecoveryKeyDescription": {}, + "separateChatTypes": "Afișați chaturi directe și grupuri separat", + "@separateChatTypes": { + "type": "text", + "placeholders": {} + }, + "setAsCanonicalAlias": "Stabiliți ca pseudonimul primar", + "@setAsCanonicalAlias": { + "type": "text", + "placeholders": {} + }, + "writeAMessage": "Scrieți un mesaj…", + "@writeAMessage": { + "type": "text", + "placeholders": {} + }, + "yes": "Da", + "@yes": { + "type": "text", + "placeholders": {} + }, + "markAsRead": "Marcați ca citit", + "@markAsRead": {}, + "oopsPushError": "Ups! Din păcate, o eroare s-a întâmplat cu stabilirea de notificări push.", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "oneClientLoggedOut": "Unul dintre clienților voștri a fost deconectat", + "@oneClientLoggedOut": {}, + "editBundlesForAccount": "Editați pachetele pentru acest cont", + "@editBundlesForAccount": {}, + "bundleName": "Numele pachetului", + "@bundleName": {}, + "link": "Link", + "@link": {}, + "passphraseOrKey": "frază de acces sau cheie de recuperare", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "password": "Parolă", + "@password": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "Parola uitată", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "Parola a fost schimbată", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "passwordRecovery": "Recuperare parolei", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "people": "Persoane", + "@people": { + "type": "text", + "placeholders": {} + }, + "pickImage": "Alegeți o imagine", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "pleaseChoose": "Vă rugăm să alegeți", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "pin": "Fixați", + "@pin": { + "type": "text", + "placeholders": {} + }, + "pleaseChooseAPasscode": "Vă rugăm să alegeți un passcode", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "Vă rugăm să introduceți 4 cifre sau puteți să lăsați gol să dezactivați lacătul aplicației.", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "Vă rugăm să introduceți parola voastră", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "Vă rugăm să introduceți username-ul vostru", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "pleaseFollowInstructionsOnWeb": "Vă rugăm să urmați instrucțiunele pe website și apoi să apăsați pe următor.", + "@pleaseFollowInstructionsOnWeb": { + "type": "text", + "placeholders": {} + }, + "reason": "Motiv", + "@reason": { + "type": "text", + "placeholders": {} + }, + "rejectedTheInvitation": "{username} a respins invitația", + "@rejectedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "redactedAnEvent": "{username} a redactat un eveniment", + "@redactedAnEvent": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removeAllOtherDevices": "Eliminați toate celelalte dispozitive", + "@removeAllOtherDevices": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "Ștergeți avatarul", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "renderRichContent": "Reda conținut bogat al mesajelor", + "@renderRichContent": { + "type": "text", + "placeholders": {} + }, + "replaceRoomWithNewerVersion": "Înlocuiți camera cu versiune mai nouă", + "@replaceRoomWithNewerVersion": { + "type": "text", + "placeholders": {} + }, + "reply": "Răspundeți", + "@reply": { + "type": "text", + "placeholders": {} + }, + "reportMessage": "Raportați mesajul", + "@reportMessage": { + "type": "text", + "placeholders": {} + }, + "requestPermission": "Cereți permisiune", + "@requestPermission": { + "type": "text", + "placeholders": {} + }, + "saveFile": "Salvați fișierul", + "@saveFile": { + "type": "text", + "placeholders": {} + }, + "search": "Căutați", + "@search": { + "type": "text", + "placeholders": {} + }, + "recoveryKey": "Cheie de recuperare", + "@recoveryKey": {}, + "recoveryKeyLost": "Cheia de recuperare pierdută?", + "@recoveryKeyLost": {}, + "seenByUser": "Văzut de {username}", + "@seenByUser": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "muteChat": "Amuțați chatul", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "Vă rugăm să fiți conștienți că e nevoie de Pantalaimon să folosiți criptare end-to-end deocamdată.", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "autoplayImages": "Anima automatic stickere și emote animate", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "sendOnEnter": "Trimite cu tasta enter", + "@sendOnEnter": {}, + "changedTheChatPermissions": "{username} a schimbat permisiunile chatului", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "extremeOffensive": "De foarte mare ofensă", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "id": "ID", + "@id": { + "type": "text", + "placeholders": {} + }, + "invitedUser": "📩{username} a invitat {targetName}", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "deviceKeys": "Cheile dispozitivului:", + "@deviceKeys": {}, + "pleaseEnterRecoveryKey": "Vă rugăm să introduceți cheia voastră de recuperare:", + "@pleaseEnterRecoveryKey": {}, + "newVerificationRequest": "Cerere de verificare nouă!", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "remove": "Eliminați", + "@remove": { + "type": "text", + "placeholders": {} + }, + "play": "Redați {fileName}", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "channelCorruptedDecryptError": "Criptarea a fost corupată", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "Alegeți o parolă robustă", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "commandHint_cuddle": "Trimiteți o îmbrățișare", + "@commandHint_cuddle": {}, + "googlyEyesContent": "{senderName} v-a trimis ochi googly", + "@googlyEyesContent": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "areYouSureYouWantToLogout": "Sunteți sigur că doriți să vă deconectați?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "changedTheRoomAliases": "{username} a schimbat pseudonimele camerei", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changeYourAvatar": "Schimbați avatarul vostru", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "commandHint_join": "Alăturați-vă la camera alesă", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "allChats": "Toate Chaturile", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "commandHint_invite": "Invitați utilizatorul ales la această cameră", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "changeTheNameOfTheGroup": "Schimbați numele grupului", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "commandHint_googly": "Trimiteți câțiva ochi googly", + "@commandHint_googly": {}, + "botMessages": "Mesaje Bot", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "all": "Toate", + "@all": { + "type": "text", + "placeholders": {} + }, + "blocked": "Blocat", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "changedTheJoinRules": "{username} a schimbat regulile de alăturare", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheProfileAvatar": "{username} s-a schimbat avatarul", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "appLock": "Lacăt aplicație", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "changedTheHistoryVisibilityTo": "{username} a schimbat vizibilitatea istoriei chatului la: {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "close": "Închideți", + "@close": { + "type": "text", + "placeholders": {} + }, + "reopenChat": "Deschide din nou chatul", + "@reopenChat": {}, + "pleaseTryAgainLaterOrChooseDifferentServer": "Vă rugăm să încercați din nou mai târziu sau să alegeți un server diferit.", + "@pleaseTryAgainLaterOrChooseDifferentServer": {}, + "signInWithPassword": "Conectați-vă cu parolă", + "@signInWithPassword": {} +} diff --git a/assets/l10n/intl_ru.arb b/assets/l10n/intl_ru.arb index 8e8021dac..2526b66db 100644 --- a/assets/l10n/intl_ru.arb +++ b/assets/l10n/intl_ru.arb @@ -2232,7 +2232,7 @@ }, "commandHint_cuddle": "Отправить улыбку", "@commandHint_cuddle": {}, - "readUpToHere": "Дочитать до сюда", + "readUpToHere": "Непрочитанное", "@readUpToHere": {}, "commandHint_hug": "Отправить обнимашки", "@commandHint_hug": {}, @@ -2369,7 +2369,7 @@ "reason": {} } }, - "setChatDescription": "Изменить описание чата", + "setChatDescription": "Установить описание чата", "@setChatDescription": {}, "setColorTheme": "Цветовая тема:", "@setColorTheme": {}, @@ -2689,5 +2689,76 @@ "@thereAreCountUsersBlocked": { "type": "text", "count": {} + }, + "restricted": "Запрещено", + "@restricted": {}, + "knockRestricted": "Стук запрещен", + "@knockRestricted": {}, + "searchIn": "Поиск в чате \"{chat}\"...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "searchMore": "Найти еще...", + "@searchMore": {}, + "gallery": "Галерея", + "@gallery": {}, + "files": "Файлы", + "@files": {}, + "swipeRightToLeftToReply": "Для ответа проведите с права на лево", + "@swipeRightToLeftToReply": {}, + "userLevel": "{level} - Пользователь", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - Модератор", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - Администратор", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeGeneralChatSettings": "Изменить общие настройки чата", + "@changeGeneralChatSettings": {}, + "changeTheChatPermissions": "Изменить права доступа к чату", + "@changeTheChatPermissions": {}, + "changeTheDescriptionOfTheGroup": "Изменить описание чата", + "@changeTheDescriptionOfTheGroup": {}, + "inviteOtherUsers": "Пригласить других пользователей в этот чат", + "@inviteOtherUsers": {}, + "changeTheVisibilityOfChatHistory": "Изменить видимость истории чата", + "@changeTheVisibilityOfChatHistory": {}, + "countChatsAndCountParticipants": "{chats} чатов и {participants} участников", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "unread": "Непрочитанные", + "@unread": {}, + "space": "Пространство", + "@space": {}, + "spaces": "Пространства", + "@spaces": {}, + "markAsUnread": "Отметить как непрочитанное", + "@markAsUnread": {}, + "goToSpace": "Перейти к пространству: {space}", + "@goToSpace": { + "type": "text", + "space": {} } } diff --git a/assets/l10n/intl_sl.arb b/assets/l10n/intl_sl.arb index c826f047d..b55d8dc7d 100644 --- a/assets/l10n/intl_sl.arb +++ b/assets/l10n/intl_sl.arb @@ -1,1984 +1,575 @@ { - "repeatPassword": "Ponovite geslo", - "@repeatPassword": {}, - "about": "O aplikaciji", - "@about": { - "type": "text", - "placeholders": {} - }, - "accept": "Sprejmi", - "@accept": { - "type": "text", - "placeholders": {} - }, - "account": "Račun", - "@account": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "Uporabnik {username} je aktiviral šifriranje od konca do konca", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "addEmail": "Dodajte e-pošto", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "addToSpace": "Dodajte v prostor", - "@addToSpace": {}, - "alias": "vzdevek", - "@alias": { - "type": "text", - "placeholders": {} - }, - "all": "Vse", - "@all": { - "type": "text", - "placeholders": {} - }, - "allChats": "Vsi klepeti", - "@allChats": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "Oseba {senderName} je odgovorila na klic", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "Pridruži se lahko vsak", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "appLock": "Zaklepanje aplikacije", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "Če želite podpisati drugo osebo, vnesite geslo za varno trgovino ali obnovitveni ključ.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "Ali želite sprejeti to zahtevo za preverjanje od {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "autoplayImages": "Samodejno predvajajte animirane nalepke in čustva", - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "badServerLoginTypesException": "Domači strežnik podpira vrste prijave:\n{serverVersions}\nToda ta aplikacija podpira samo:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "sendOnEnter": "Pošlji ob vstopu", - "@sendOnEnter": {}, - "banFromChat": "Prepoved klepeta", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "Prepovedano", - "@banned": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "{username} je prepovedan v {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "blockDevice": "Blokirana naprava", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "Blokirano", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "botMessages": "Botova sporočila", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "cancel": "Prekliči", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "cantOpenUri": "URI-ja {uri} ni mogoče odpreti", - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "changedTheChatAvatar": "{username} je spremenil avatar za klepet", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatPermissions": "{username} je spremenila dovoljenja za klepet", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "{username} je spremenil svoje prikazno ime v: '{displayname}'", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRules": "{username} je spremenila pravila dostopa za goste", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} je spremenila pravila dostopa za goste v: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheHistoryVisibilityTo": "{username} je spremenil vidnost zgodovine v: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username} je spremenil pravila za pridružitev", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "{username} je spremenila pravila pridružitve v: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheProfileAvatar": "{username} je spremenil avatar", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "{username} je spremenil vzdevke sobe", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomInvitationLink": "{username} je spremenil povezavo za povabilo", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changePassword": "Spremeni geslo", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "changeTheHomeserver": "Spremenite domači strežnik", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "Spremenite svoj slog", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "Spremenite ime skupine", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "Spremenite svoj avatar", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "chat": "Klepet", - "@chat": { - "type": "text", - "placeholders": {} - }, - "yourChatBackupHasBeenSetUp": "Varnostna kopija klepeta je nastavljena.", - "@yourChatBackupHasBeenSetUp": {}, - "chatBackup": "Varnostno kopiranje klepeta", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "Podrobnosti klepeta", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chatHasBeenAddedToThisSpace": "Klepet je bil dodan v ta prostor", - "@chatHasBeenAddedToThisSpace": {}, - "chats": "Klepeti", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "Izberite močno geslo", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "Počisti arhiv", - "@clearArchive": {}, - "close": "Zapri", - "@close": { - "type": "text", - "placeholders": {} - }, - "commandHint_ban": "Izključi določenega uporabnika iz te sobe", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_html": "Pošljite besedilo v obliki HTML", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "Povabi danega uporabnika v to sobo", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_join": "Pridružite se dani sobi", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_kick": "Odstranite danega uporabnika iz te sobe", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_me": "Opisi sebe", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "commandHint_myroomavatar": "Nastavite svojo sliko za to sobo", - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "commandHint_op": "Nastavite raven moči danega uporabnika (privzeto: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_react": "Pošljite odgovor kot reakcijo", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandHint_send": "Pošlji besedilo", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandHint_unban": "Prekliči izključitev določenega uporabnika iz te sobe", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "commandInvalid": "Ukaz ni veljaven", - "@commandInvalid": { - "type": "text" - }, - "commandMissing": "{command} is not a command.", - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "compareEmojiMatch": "Primerjajte in se prepričajte, da se naslednji emoji ujemajo s tistimi iz druge naprave:", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Primerjajte in se prepričajte, da se naslednje številke ujemajo s številkami druge naprave:", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "configureChat": "Konfigurirajte klepet", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "confirm": "Potrdi", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "Vsebuje prikazno ime", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "Vsebuje uporabniško ime", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "archive": "Arhiv", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "Ali si prepričan?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "{username} je sprejel povabilo", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "areYouSureYouWantToLogout": "Ali ste prepričani, da se želite odjaviti?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "changedTheChatDescriptionTo": "{username} je spremenil opis klepeta v: '{description}'", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "areGuestsAllowedToJoin": "Ali se lahko gostujoči uporabniki pridružijo", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "admin": "Admin", - "@admin": { - "type": "text", - "placeholders": {} - }, - "badServerVersionsException": "Domači strežnik podpira različice Spec:\n{serverVersions}\nToda ta aplikacija podpira samo {supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "changedTheChatNameTo": "{username} je spremenil ime klepeta v: '{chatname}'", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changeDeviceName": "Spremenite ime naprave", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheHistoryVisibility": "{username} je spremenila vidnost zgodovine", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "channelCorruptedDecryptError": "Šifriranje je poškodovano", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "Vsebina je bila prijavljena skrbnikom strežnika", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "Varnostna kopija klepeta je zavarovana z varnostnim ključem. Prosimo, pazite, da ga ne izgubite.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "commandHint_myroomnick": "Nastavite prikazno ime za to sobo", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "connect": "Povežite se", - "@connect": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "Kontakt je bil povabljen v skupino", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "commandHint_leave": "Zapusti to sobo", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_plain": "Pošlji neformatirano besedilo", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "copiedToClipboard": "Kopirano v odložišče", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "copy": "Kopiraj", - "@copy": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "Kopiraj v odložišče", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Sporočila ni bilo mogoče dešifrirati: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "countParticipants": "{count} udeležencev", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "create": "Ustvari", - "@create": { - "type": "text", - "placeholders": {} - }, - "createNewSpace": "Nov prostor", - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "currentlyActive": "Trenutno aktiven", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "Temno", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "Privzeta raven dovoljenja", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "dateWithYear": "{day}-{month}-{year}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "dateWithoutYear": "{month}-{day}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "createdTheChat": "{username} je ustvaril klepet", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "deactivateAccountWarning": "S tem boste deaktivirali vaš uporabniški račun. Tega ni mogoče razveljaviti! Ali si prepričan?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@widgetVideo": {}, - "@dismiss": {}, - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "@reportErrorDescription": {}, - "@directChats": { - "type": "text", - "placeholders": {} - }, - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "@addAccount": {}, - "@reply": { - "type": "text", - "placeholders": {} - }, - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "@unsupportedAndroidVersion": {}, - "@device": { - "type": "text", - "placeholders": {} - }, - "@widgetJitsi": {}, - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "@encryption": { - "type": "text", - "placeholders": {} - }, - "@messageType": {}, - "@indexedDbErrorLong": {}, - "@oneClientLoggedOut": {}, - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "@startFirstChat": {}, - "@callingAccount": {}, - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@invited": { - "type": "text", - "placeholders": {} - }, - "@setColorTheme": {}, - "@nextAccount": {}, - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "@warning": { - "type": "text", - "placeholders": {} - }, - "@password": { - "type": "text", - "placeholders": {} - }, - "@allSpaces": {}, - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "@user": {}, - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "@youAcceptedTheInvitation": {}, - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@banUserDescription": {}, - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "@widgetEtherpad": {}, - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "@remove": { - "type": "text", - "placeholders": {} - }, - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "@id": { - "type": "text", - "placeholders": {} - }, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "@unbanUserDescription": {}, - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "@youRejectedTheInvitation": {}, - "@otherCallingPermissions": {}, - "@messagesStyle": {}, - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "@link": {}, - "@widgetUrlError": {}, - "@emailOrUsername": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@next": { - "type": "text", - "placeholders": {} - }, - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "@enterSpace": {}, - "@encryptThisChat": {}, - "@fileName": { - "type": "text", - "placeholders": {} - }, - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "@previousAccount": {}, - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "@reopenChat": {}, - "@pleaseEnterRecoveryKey": {}, - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "@no": { - "type": "text", - "placeholders": {} - }, - "@widgetNameError": {}, - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "@unpin": { - "type": "text", - "placeholders": {} - }, - "@addToBundle": {}, - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "@addWidget": {}, - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "@noKeyForThisMessage": {}, - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "@reason": { - "type": "text", - "placeholders": {} - }, - "@commandHint_markasgroup": {}, - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "@hydrateTor": {}, - "@pushNotificationsNotAvailable": {}, - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "@storeInAppleKeyChain": {}, - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "@hydrate": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "@sender": {}, - "@storeInAndroidKeystore": {}, - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "@online": { - "type": "text", - "placeholders": {} - }, - "@signInWithPassword": {}, - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "@offensive": { - "type": "text", - "placeholders": {} - }, - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "@makeAdminDescription": {}, - "@edit": { - "type": "text", - "placeholders": {} - }, - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "@saveKeyManuallyDescription": {}, - "@none": { - "type": "text", - "placeholders": {} - }, - "@editBundlesForAccount": {}, - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "@whyIsThisMessageEncrypted": {}, - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@setChatDescription": {}, - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "@importFromZipFile": {}, - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "@or": { - "type": "text", - "placeholders": {} - }, - "@dehydrateWarning": {}, - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "@noOtherDevicesFound": {}, - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@submit": { - "type": "text", - "placeholders": {} - }, - "@videoCallsBetaWarning": {}, - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@participant": { - "type": "text", - "placeholders": {} - }, - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "@yes": { - "type": "text", - "placeholders": {} - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@username": { - "type": "text", - "placeholders": {} - }, - "@fileIsTooBigForServer": {}, - "@homeserver": {}, - "@help": { - "type": "text", - "placeholders": {} - }, - "@people": { - "type": "text", - "placeholders": {} - }, - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "@verified": { - "type": "text", - "placeholders": {} - }, - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "@callingPermissions": {}, - "@delete": { - "type": "text", - "placeholders": {} - }, - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "@readUpToHere": {}, - "@start": {}, - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "@register": { - "type": "text", - "placeholders": {} - }, - "@unlockOldMessages": {}, - "@identity": { - "type": "text", - "placeholders": {} - }, - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@ignore": { - "type": "text", - "placeholders": {} - }, - "@recording": { - "type": "text", - "placeholders": {} - }, - "@moderator": { - "type": "text", - "placeholders": {} - }, - "@optionalRedactReason": {}, - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "@ok": { - "type": "text", - "placeholders": {} - }, - "@dehydrate": {}, - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "@send": { - "type": "text", - "placeholders": {} - }, - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "@sendAsText": { - "type": "text" - }, - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@newChat": { - "type": "text", - "placeholders": {} - }, - "@notifications": { - "type": "text", - "placeholders": {} - }, - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "@experimentalVideoCalls": {}, - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "@pleaseEnterRecoveryKeyDescription": {}, - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "@mention": { - "type": "text", - "placeholders": {} - }, - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroupQuestion": {}, - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "@group": { - "type": "text", - "placeholders": {} - }, - "@leave": { - "type": "text", - "placeholders": {} - }, - "@skip": { - "type": "text", - "placeholders": {} - }, - "@appearOnTopDetails": {}, - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "@enterRoom": {}, - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "@reportUser": {}, - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "@confirmEventUnpin": {}, - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@license": { - "type": "text", - "placeholders": {} - }, - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "@redactMessageDescription": {}, - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "@recoveryKey": {}, - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "@forward": { - "type": "text", - "placeholders": {} - }, - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "@invalidInput": {}, - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "@dehydrateTorLong": {}, - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "@offline": { - "type": "text", - "placeholders": {} - }, - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "@doNotShowAgain": {}, - "@report": {}, - "@status": { - "type": "text", - "placeholders": {} - }, - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "@unverified": {}, - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "@serverRequiresEmail": {}, - "@hideUnimportantStateEvents": {}, - "@screenSharingTitle": {}, - "@widgetCustom": {}, - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@addToSpaceDescription": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "@addChatDescription": {}, - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@publish": {}, - "@openLinkInBrowser": {}, - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "@messageInfo": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "@foregroundServiceRunning": {}, - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "@voiceCall": {}, - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "@noChatDescriptionYet": {}, - "@removeFromBundle": {}, - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "@confirmMatrixId": {}, - "@learnMore": {}, - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "@you": { - "type": "text", - "placeholders": {} - }, - "@notAnImage": {}, - "@users": {}, - "@openGallery": {}, - "@chatDescriptionHasBeenChanged": {}, - "@search": { - "type": "text", - "placeholders": {} - }, - "@newGroup": {}, - "@bundleName": {}, - "@dehydrateTor": {}, - "@removeFromSpace": {}, - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "@roomUpgradeDescription": {}, - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "@scanQrCode": {}, - "@logout": { - "type": "text", - "placeholders": {} - }, - "@pleaseEnterANumber": {}, - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "@profileNotFound": {}, - "@jump": {}, - "@groups": { - "type": "text", - "placeholders": {} - }, - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "@sorryThatsNotPossible": {}, - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "@shareInviteLink": {}, - "@commandHint_markasdm": {}, - "@recoveryKeyLost": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@messages": { - "type": "text", - "placeholders": {} - }, - "@login": { - "type": "text", - "placeholders": {} - }, - "@deviceKeys": {}, - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "@settings": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@youJoinedTheChat": {}, - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "@security": { - "type": "text", - "placeholders": {} - }, - "@markAsRead": {}, - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "@widgetName": {}, - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@errorAddingWidget": {}, - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "@commandHint_hug": {}, - "@replace": {}, - "@reject": { - "type": "text", - "placeholders": {} - }, - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "@newSpace": {}, - "@devices": { - "type": "text", - "placeholders": {} - }, - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "@emojis": {}, - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "@share": { - "type": "text", - "placeholders": {} - }, - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@privacy": { - "type": "text", - "placeholders": {} - }, - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "@hydrateTorLong": {}, - "@time": {}, - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "@custom": {}, - "@noBackupWarning": {}, - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "@verify": { - "type": "text", - "placeholders": {} - }, - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "@storeInSecureStorageDescription": {}, - "@openChat": {}, - "@kickUserDescription": {}, - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "@pin": { - "type": "text", - "placeholders": {} - }, - "@importNow": {}, - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "@pinMessage": {}, - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "@invite": {}, - "@enableMultiAccounts": {}, - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "@indexedDbErrorTitle": {}, - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@unsupportedAndroidVersionLong": {}, - "@storeSecurlyOnThisDevice": {}, - "@screenSharingDetail": {}, - "@placeCall": {} -} \ No newline at end of file + "repeatPassword": "Ponovite geslo", + "@repeatPassword": {}, + "about": "O aplikaciji", + "@about": { + "type": "text", + "placeholders": {} + }, + "accept": "Sprejmi", + "@accept": { + "type": "text", + "placeholders": {} + }, + "account": "Račun", + "@account": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "Uporabnik {username} je aktiviral šifriranje od konca do konca", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "addEmail": "Dodajte e-pošto", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "addToSpace": "Dodajte v prostor", + "@addToSpace": {}, + "alias": "vzdevek", + "@alias": { + "type": "text", + "placeholders": {} + }, + "all": "Vse", + "@all": { + "type": "text", + "placeholders": {} + }, + "allChats": "Vsi klepeti", + "@allChats": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "Oseba {senderName} je odgovorila na klic", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "anyoneCanJoin": "Pridruži se lahko vsak", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "appLock": "Zaklepanje aplikacije", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "askSSSSSign": "Če želite podpisati drugo osebo, vnesite geslo za varno trgovino ali obnovitveni ključ.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "Ali želite sprejeti to zahtevo za preverjanje od {username}?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "autoplayImages": "Samodejno predvajajte animirane nalepke in čustva", + "@autoplayImages": { + "type": "text", + "placeholder": {} + }, + "badServerLoginTypesException": "Domači strežnik podpira vrste prijave:\n{serverVersions}\nToda ta aplikacija podpira samo:\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "sendOnEnter": "Pošlji ob vstopu", + "@sendOnEnter": {}, + "banFromChat": "Prepoved klepeta", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "banned": "Prepovedano", + "@banned": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "{username} je prepovedan v {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "blockDevice": "Blokirana naprava", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "blocked": "Blokirano", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "botMessages": "Botova sporočila", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "cancel": "Prekliči", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "cantOpenUri": "URI-ja {uri} ni mogoče odpreti", + "@cantOpenUri": { + "type": "text", + "placeholders": { + "uri": {} + } + }, + "changedTheChatAvatar": "{username} je spremenil avatar za klepet", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatPermissions": "{username} je spremenila dovoljenja za klepet", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "{username} je spremenil svoje prikazno ime v: '{displayname}'", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRules": "{username} je spremenila pravila dostopa za goste", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheGuestAccessRulesTo": "{username} je spremenila pravila dostopa za goste v: {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheHistoryVisibilityTo": "{username} je spremenil vidnost zgodovine v: {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRules": "{username} je spremenil pravila za pridružitev", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheJoinRulesTo": "{username} je spremenila pravila pridružitve v: {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheProfileAvatar": "{username} je spremenil avatar", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "{username} je spremenil vzdevke sobe", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomInvitationLink": "{username} je spremenil povezavo za povabilo", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changePassword": "Spremeni geslo", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "changeTheHomeserver": "Spremenite domači strežnik", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "Spremenite svoj slog", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "Spremenite ime skupine", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "changeYourAvatar": "Spremenite svoj avatar", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "chat": "Klepet", + "@chat": { + "type": "text", + "placeholders": {} + }, + "yourChatBackupHasBeenSetUp": "Varnostna kopija klepeta je nastavljena.", + "@yourChatBackupHasBeenSetUp": {}, + "chatBackup": "Varnostno kopiranje klepeta", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "chatDetails": "Podrobnosti klepeta", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chatHasBeenAddedToThisSpace": "Klepet je bil dodan v ta prostor", + "@chatHasBeenAddedToThisSpace": {}, + "chats": "Klepeti", + "@chats": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "Izberite močno geslo", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "clearArchive": "Počisti arhiv", + "@clearArchive": {}, + "close": "Zapri", + "@close": { + "type": "text", + "placeholders": {} + }, + "commandHint_ban": "Izključi določenega uporabnika iz te sobe", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_html": "Pošljite besedilo v obliki HTML", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_invite": "Povabi danega uporabnika v to sobo", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "commandHint_join": "Pridružite se dani sobi", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_kick": "Odstranite danega uporabnika iz te sobe", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_me": "Opisi sebe", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "commandHint_myroomavatar": "Nastavite svojo sliko za to sobo", + "@commandHint_myroomavatar": { + "type": "text", + "description": "Usage hint for the command /myroomavatar" + }, + "commandHint_op": "Nastavite raven moči danega uporabnika (privzeto: 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_react": "Pošljite odgovor kot reakcijo", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "commandHint_send": "Pošlji besedilo", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "commandHint_unban": "Prekliči izključitev določenega uporabnika iz te sobe", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "commandInvalid": "Ukaz ni veljaven", + "@commandInvalid": { + "type": "text" + }, + "commandMissing": "{command} is not a command.", + "@commandMissing": { + "type": "text", + "placeholders": { + "command": {} + }, + "description": "State that {command} is not a valid /command." + }, + "compareEmojiMatch": "Primerjajte in se prepričajte, da se naslednji emoji ujemajo s tistimi iz druge naprave:", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "Primerjajte in se prepričajte, da se naslednje številke ujemajo s številkami druge naprave:", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "configureChat": "Konfigurirajte klepet", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "confirm": "Potrdi", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "Vsebuje prikazno ime", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "containsUserName": "Vsebuje uporabniško ime", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "archive": "Arhiv", + "@archive": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "Ali si prepričan?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "{username} je sprejel povabilo", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "areYouSureYouWantToLogout": "Ali ste prepričani, da se želite odjaviti?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "changedTheChatDescriptionTo": "{username} je spremenil opis klepeta v: '{description}'", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "areGuestsAllowedToJoin": "Ali se lahko gostujoči uporabniki pridružijo", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "admin": "Admin", + "@admin": { + "type": "text", + "placeholders": {} + }, + "badServerVersionsException": "Domači strežnik podpira različice Spec:\n{serverVersions}\nToda ta aplikacija podpira samo {supportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "changedTheChatNameTo": "{username} je spremenil ime klepeta v: '{chatname}'", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changeDeviceName": "Spremenite ime naprave", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "changedTheHistoryVisibility": "{username} je spremenila vidnost zgodovine", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "channelCorruptedDecryptError": "Šifriranje je poškodovano", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "Vsebina je bila prijavljena skrbnikom strežnika", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "chatBackupDescription": "Varnostna kopija klepeta je zavarovana z varnostnim ključem. Prosimo, pazite, da ga ne izgubite.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "commandHint_myroomnick": "Nastavite prikazno ime za to sobo", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "connect": "Povežite se", + "@connect": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "Kontakt je bil povabljen v skupino", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "commandHint_leave": "Zapusti to sobo", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_plain": "Pošlji neformatirano besedilo", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "copiedToClipboard": "Kopirano v odložišče", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "copy": "Kopiraj", + "@copy": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "Kopiraj v odložišče", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "Sporočila ni bilo mogoče dešifrirati: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "countParticipants": "{count} udeležencev", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "create": "Ustvari", + "@create": { + "type": "text", + "placeholders": {} + }, + "createNewSpace": "Nov prostor", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "currentlyActive": "Trenutno aktiven", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "Temno", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "Privzeta raven dovoljenja", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "dateWithYear": "{day}-{month}-{year}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "dateWithoutYear": "{month}-{day}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "createdTheChat": "{username} je ustvaril klepet", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "deactivateAccountWarning": "S tem boste deaktivirali vaš uporabniški račun. Tega ni mogoče razveljaviti! Ali si prepričan?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + } +} diff --git a/assets/l10n/intl_sr.arb b/assets/l10n/intl_sr.arb index 2b0564d85..afebfa2db 100644 --- a/assets/l10n/intl_sr.arb +++ b/assets/l10n/intl_sr.arb @@ -1,2213 +1,1805 @@ { - "@@last_modified": "2021-08-14 12:41:09.857024", - "about": "О програму", - "@about": { - "type": "text", - "placeholders": {} - }, - "accept": "Прихвати", - "@accept": { - "type": "text", - "placeholders": {} - }, - "acceptedTheInvitation": "{username} прихвата позивницу", - "@acceptedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "account": "Налог", - "@account": { - "type": "text", - "placeholders": {} - }, - "activatedEndToEndEncryption": "{username} укључи шифровање с краја на крај", - "@activatedEndToEndEncryption": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "addEmail": "Додај е-адресу", - "@addEmail": { - "type": "text", - "placeholders": {} - }, - "admin": "Админ", - "@admin": { - "type": "text", - "placeholders": {} - }, - "alias": "алијас", - "@alias": { - "type": "text", - "placeholders": {} - }, - "all": "Сви", - "@all": { - "type": "text", - "placeholders": {} - }, - "answeredTheCall": "{senderName} одговори на позив", - "@answeredTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "anyoneCanJoin": "свако може да се придружи", - "@anyoneCanJoin": { - "type": "text", - "placeholders": {} - }, - "appLock": "Закључавање апликације", - "@appLock": { - "type": "text", - "placeholders": {} - }, - "archive": "Архива", - "@archive": { - "type": "text", - "placeholders": {} - }, - "areGuestsAllowedToJoin": "Да ли је гостима дозвољен приступ", - "@areGuestsAllowedToJoin": { - "type": "text", - "placeholders": {} - }, - "areYouSure": "Сигурни сте?", - "@areYouSure": { - "type": "text", - "placeholders": {} - }, - "areYouSureYouWantToLogout": "Заиста желите да се одјавите?", - "@areYouSureYouWantToLogout": { - "type": "text", - "placeholders": {} - }, - "askSSSSSign": "Да бисте могли да пријавите другу особу, унесите своју безбедносну фразу или кључ опоравка.", - "@askSSSSSign": { - "type": "text", - "placeholders": {} - }, - "askVerificationRequest": "Прихватате ли захтев за верификацију од корисника {username}?", - "@askVerificationRequest": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "badServerLoginTypesException": "Домаћи сервер подржава начине пријаве:\n{serverVersions}\nали ова апликација подржава само:\n{supportedVersions}", - "@badServerLoginTypesException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "badServerVersionsException": "Домаћи сервер подржава верзије:\n{serverVersions}\nали ова апликација подржава само {supportedVersions}", - "@badServerVersionsException": { - "type": "text", - "placeholders": { - "serverVersions": {}, - "supportedVersions": {} - } - }, - "banFromChat": "Забрани у ћаскању", - "@banFromChat": { - "type": "text", - "placeholders": {} - }, - "banned": "Забрањен", - "@banned": { - "type": "text", - "placeholders": {} - }, - "bannedUser": "{username} забрани корисника {targetName}", - "@bannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "blockDevice": "Блокирај уређај", - "@blockDevice": { - "type": "text", - "placeholders": {} - }, - "blocked": "Блокиран", - "@blocked": { - "type": "text", - "placeholders": {} - }, - "botMessages": "Поруке Бота", - "@botMessages": { - "type": "text", - "placeholders": {} - }, - "cancel": "Откажи", - "@cancel": { - "type": "text", - "placeholders": {} - }, - "changeDeviceName": "Промени назив уређаја", - "@changeDeviceName": { - "type": "text", - "placeholders": {} - }, - "changedTheChatAvatar": "{username} промени аватар ћаскања", - "@changedTheChatAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheChatDescriptionTo": "{username} промени опис ћаскања у: „{description}“", - "@changedTheChatDescriptionTo": { - "type": "text", - "placeholders": { - "username": {}, - "description": {} - } - }, - "changedTheChatNameTo": "{username} промени назив ћаскања у: „{chatname}“", - "@changedTheChatNameTo": { - "type": "text", - "placeholders": { - "username": {}, - "chatname": {} - } - }, - "changedTheChatPermissions": "{username} измени дозволе ћаскања", - "@changedTheChatPermissions": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheDisplaynameTo": "{username} промени приказно име на: „{displayname}“", - "@changedTheDisplaynameTo": { - "type": "text", - "placeholders": { - "username": {}, - "displayname": {} - } - }, - "changedTheGuestAccessRules": "{username} измени правила за приступ гостију", - "@changedTheGuestAccessRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheGuestAccessRulesTo": "{username} измени правила за приступ гостију на: {rules}", - "@changedTheGuestAccessRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheHistoryVisibility": "{username} измени видљивост историје", - "@changedTheHistoryVisibility": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheHistoryVisibilityTo": "{username} измени видљивост историје на: {rules}", - "@changedTheHistoryVisibilityTo": { - "type": "text", - "placeholders": { - "username": {}, - "rules": {} - } - }, - "changedTheJoinRules": "{username} измени правила приступања", - "@changedTheJoinRules": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheJoinRulesTo": "{username} измени правила приступања на: {joinRules}", - "@changedTheJoinRulesTo": { - "type": "text", - "placeholders": { - "username": {}, - "joinRules": {} - } - }, - "changedTheProfileAvatar": "{username} измени свој аватар", - "@changedTheProfileAvatar": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomAliases": "{username} измени алијас собе", - "@changedTheRoomAliases": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changedTheRoomInvitationLink": "{username} измени везу позивнице", - "@changedTheRoomInvitationLink": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "changePassword": "Измени лозинку", - "@changePassword": { - "type": "text", - "placeholders": {} - }, - "changeTheHomeserver": "Промени домаћи сервер", - "@changeTheHomeserver": { - "type": "text", - "placeholders": {} - }, - "changeTheme": "Измените изглед", - "@changeTheme": { - "type": "text", - "placeholders": {} - }, - "changeTheNameOfTheGroup": "Измени назив групе", - "@changeTheNameOfTheGroup": { - "type": "text", - "placeholders": {} - }, - "changeYourAvatar": "Измените свој аватар", - "@changeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "channelCorruptedDecryptError": "Шифровање је покварено", - "@channelCorruptedDecryptError": { - "type": "text", - "placeholders": {} - }, - "chat": "Ћаскање", - "@chat": { - "type": "text", - "placeholders": {} - }, - "chatBackup": "Копија ћаскања", - "@chatBackup": { - "type": "text", - "placeholders": {} - }, - "chatBackupDescription": "Ваша резервна копија ћаскања је обезбеђена кључем. Немојте да га изгубите.", - "@chatBackupDescription": { - "type": "text", - "placeholders": {} - }, - "chatDetails": "Детаљи ћаскања", - "@chatDetails": { - "type": "text", - "placeholders": {} - }, - "chats": "Ћаскања", - "@chats": { - "type": "text", - "placeholders": {} - }, - "chooseAStrongPassword": "Изаберите јаку лозинку", - "@chooseAStrongPassword": { - "type": "text", - "placeholders": {} - }, - "clearArchive": "Очисти архиву", - "@clearArchive": {}, - "close": "Затвори", - "@close": { - "type": "text", - "placeholders": {} - }, - "commandHint_ban": "Блокирај задатог корисника за ову собу", - "@commandHint_ban": { - "type": "text", - "description": "Usage hint for the command /ban" - }, - "commandHint_html": "Шаљи ХТМЛ обликован текст", - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "commandHint_invite": "Позови задатог корисника у собу", - "@commandHint_invite": { - "type": "text", - "description": "Usage hint for the command /invite" - }, - "commandHint_join": "Придружи се наведеној соби", - "@commandHint_join": { - "type": "text", - "description": "Usage hint for the command /join" - }, - "commandHint_kick": "Уклони задатог корисника из собе", - "@commandHint_kick": { - "type": "text", - "description": "Usage hint for the command /kick" - }, - "commandHint_leave": "Напусти ову собу", - "@commandHint_leave": { - "type": "text", - "description": "Usage hint for the command /leave" - }, - "commandHint_me": "Опишите себе", - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" - }, - "commandHint_myroomnick": "Поставља ваш надимак за ову собу", - "@commandHint_myroomnick": { - "type": "text", - "description": "Usage hint for the command /myroomnick" - }, - "commandHint_op": "Подеси ниво задатог корисника (подразумевано: 50)", - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "commandHint_plain": "Шаљи неформатиран текст", - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "commandHint_react": "Шаљи одговор као реакцију", - "@commandHint_react": { - "type": "text", - "description": "Usage hint for the command /react" - }, - "commandHint_send": "Пошаљи текст", - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "commandHint_unban": "Скини забрану задатом кориснику за ову собу", - "@commandHint_unban": { - "type": "text", - "description": "Usage hint for the command /unban" - }, - "compareEmojiMatch": "Упоредите и проверите да су емоџији идентични као на другом уређају:", - "@compareEmojiMatch": { - "type": "text", - "placeholders": {} - }, - "compareNumbersMatch": "Упоредите и проверите да су следећи бројеви идентични као на другом уређају:", - "@compareNumbersMatch": { - "type": "text", - "placeholders": {} - }, - "configureChat": "Подешавање ћаскања", - "@configureChat": { - "type": "text", - "placeholders": {} - }, - "confirm": "Потврди", - "@confirm": { - "type": "text", - "placeholders": {} - }, - "connect": "Повежи се", - "@connect": { - "type": "text", - "placeholders": {} - }, - "contactHasBeenInvitedToTheGroup": "Особа је позвана у групу", - "@contactHasBeenInvitedToTheGroup": { - "type": "text", - "placeholders": {} - }, - "containsDisplayName": "Садржи приказно име", - "@containsDisplayName": { - "type": "text", - "placeholders": {} - }, - "containsUserName": "Садржи корисничко име", - "@containsUserName": { - "type": "text", - "placeholders": {} - }, - "contentHasBeenReported": "Садржај је пријављен администраторима сервера", - "@contentHasBeenReported": { - "type": "text", - "placeholders": {} - }, - "copiedToClipboard": "Копирано у клипборд", - "@copiedToClipboard": { - "type": "text", - "placeholders": {} - }, - "copy": "Копирај", - "@copy": { - "type": "text", - "placeholders": {} - }, - "copyToClipboard": "Копирај у клипборд", - "@copyToClipboard": { - "type": "text", - "placeholders": {} - }, - "couldNotDecryptMessage": "Не могу да дешифрујем поруку: {error}", - "@couldNotDecryptMessage": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "countParticipants": "учесника: {count}", - "@countParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "create": "Направи", - "@create": { - "type": "text", - "placeholders": {} - }, - "createdTheChat": "{username} направи ћаскање", - "@createdTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "currentlyActive": "Тренутно активно", - "@currentlyActive": { - "type": "text", - "placeholders": {} - }, - "darkTheme": "тамни", - "@darkTheme": { - "type": "text", - "placeholders": {} - }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", - "@dateAndTimeOfDay": { - "type": "text", - "placeholders": { - "date": {}, - "timeOfDay": {} - } - }, - "dateWithoutYear": "{day} {month}", - "@dateWithoutYear": { - "type": "text", - "placeholders": { - "month": {}, - "day": {} - } - }, - "dateWithYear": "{day} {month} {year}", - "@dateWithYear": { - "type": "text", - "placeholders": { - "year": {}, - "month": {}, - "day": {} - } - }, - "deactivateAccountWarning": "Ово ће деактивирати ваш кориснички налог. Не може се повратити! Сигурни сте?", - "@deactivateAccountWarning": { - "type": "text", - "placeholders": {} - }, - "defaultPermissionLevel": "Подразумевани ниво приступа", - "@defaultPermissionLevel": { - "type": "text", - "placeholders": {} - }, - "delete": "Обриши", - "@delete": { - "type": "text", - "placeholders": {} - }, - "deleteAccount": "Обриши налог", - "@deleteAccount": { - "type": "text", - "placeholders": {} - }, - "deleteMessage": "Брисање поруке", - "@deleteMessage": { - "type": "text", - "placeholders": {} - }, - "device": "Уређај", - "@device": { - "type": "text", - "placeholders": {} - }, - "deviceId": "ИД уређаја", - "@deviceId": { - "type": "text", - "placeholders": {} - }, - "devices": "Уређаји", - "@devices": { - "type": "text", - "placeholders": {} - }, - "directChats": "Директна ћаскања", - "@directChats": { - "type": "text", - "placeholders": {} - }, - "displaynameHasBeenChanged": "Име за приказ је измењено", - "@displaynameHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "downloadFile": "Преузми фајл", - "@downloadFile": { - "type": "text", - "placeholders": {} - }, - "edit": "Уреди", - "@edit": { - "type": "text", - "placeholders": {} - }, - "editBlockedServers": "Уреди блокиране сервере", - "@editBlockedServers": { - "type": "text", - "placeholders": {} - }, - "editDisplayname": "Уреди име за приказ", - "@editDisplayname": { - "type": "text", - "placeholders": {} - }, - "editRoomAliases": "Уреди алијасе собе", - "@editRoomAliases": { - "type": "text", - "placeholders": {} - }, - "editRoomAvatar": "Уређује аватар собе", - "@editRoomAvatar": { - "type": "text", - "placeholders": {} - }, - "emoteExists": "Емоти већ постоји!", - "@emoteExists": { - "type": "text", - "placeholders": {} - }, - "emoteInvalid": "Неисправна скраћеница за емоти!", - "@emoteInvalid": { - "type": "text", - "placeholders": {} - }, - "emotePacks": "Пакети емотија за собу", - "@emotePacks": { - "type": "text", - "placeholders": {} - }, - "emoteSettings": "Поставке емотија", - "@emoteSettings": { - "type": "text", - "placeholders": {} - }, - "emoteShortcode": "скраћеница", - "@emoteShortcode": { - "type": "text", - "placeholders": {} - }, - "emoteWarnNeedToPick": "Морате да изаберете скраћеницу и слику за емоти!", - "@emoteWarnNeedToPick": { - "type": "text", - "placeholders": {} - }, - "emptyChat": "празно ћаскање", - "@emptyChat": { - "type": "text", - "placeholders": {} - }, - "enableEmotesGlobally": "Глобално укључи пакет емотија", - "@enableEmotesGlobally": { - "type": "text", - "placeholders": {} - }, - "enableEncryption": "Укључује шифровање", - "@enableEncryption": { - "type": "text", - "placeholders": {} - }, - "enableEncryptionWarning": "Шифровање више нећете моћи да искључите. Сигурни сте?", - "@enableEncryptionWarning": { - "type": "text", - "placeholders": {} - }, - "encrypted": "Шифровано", - "@encrypted": { - "type": "text", - "placeholders": {} - }, - "encryption": "Шифровање", - "@encryption": { - "type": "text", - "placeholders": {} - }, - "encryptionNotEnabled": "Шифровање није укључено", - "@encryptionNotEnabled": { - "type": "text", - "placeholders": {} - }, - "endedTheCall": "{senderName} заврши позив", - "@endedTheCall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "enterAnEmailAddress": "Унесите адресу е-поште", - "@enterAnEmailAddress": { - "type": "text", - "placeholders": {} - }, - "enterYourHomeserver": "Унесите свој домаћи сервер", - "@enterYourHomeserver": { - "type": "text", - "placeholders": {} - }, - "everythingReady": "Све је спремно!", - "@everythingReady": { - "type": "text", - "placeholders": {} - }, - "extremeOffensive": "Екстремно увредљив", - "@extremeOffensive": { - "type": "text", - "placeholders": {} - }, - "fileName": "Назив фајла", - "@fileName": { - "type": "text", - "placeholders": {} - }, - "fluffychat": "FluffyChat", - "@fluffychat": { - "type": "text", - "placeholders": {} - }, - "fontSize": "Величина фонта", - "@fontSize": { - "type": "text", - "placeholders": {} - }, - "forward": "Напред", - "@forward": { - "type": "text", - "placeholders": {} - }, - "fromJoining": "од приступања", - "@fromJoining": { - "type": "text", - "placeholders": {} - }, - "fromTheInvitation": "од позивања", - "@fromTheInvitation": { - "type": "text", - "placeholders": {} - }, - "goToTheNewRoom": "Иди у нову собу", - "@goToTheNewRoom": { - "type": "text", - "placeholders": {} - }, - "group": "Група", - "@group": { - "type": "text", - "placeholders": {} - }, - "groupIsPublic": "Група је јавна", - "@groupIsPublic": { - "type": "text", - "placeholders": {} - }, - "groups": "Групе", - "@groups": { - "type": "text", - "placeholders": {} - }, - "groupWith": "Група са корисником {displayname}", - "@groupWith": { - "type": "text", - "placeholders": { - "displayname": {} - } - }, - "guestsAreForbidden": "гости су забрањени", - "@guestsAreForbidden": { - "type": "text", - "placeholders": {} - }, - "guestsCanJoin": "гости могу приступити", - "@guestsCanJoin": { - "type": "text", - "placeholders": {} - }, - "hasWithdrawnTheInvitationFor": "{username} поништи позивницу за корисника {targetName}", - "@hasWithdrawnTheInvitationFor": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "help": "Помоћ", - "@help": { - "type": "text", - "placeholders": {} - }, - "hideRedactedEvents": "Сакриј редиговане догађаје", - "@hideRedactedEvents": { - "type": "text", - "placeholders": {} - }, - "hideUnknownEvents": "Сакриј непознате догађаје", - "@hideUnknownEvents": { - "type": "text", - "placeholders": {} - }, - "howOffensiveIsThisContent": "Колико је увредљив овај садржај?", - "@howOffensiveIsThisContent": { - "type": "text", - "placeholders": {} - }, - "id": "ИД", - "@id": { - "type": "text", - "placeholders": {} - }, - "identity": "Идентитет", - "@identity": { - "type": "text", - "placeholders": {} - }, - "ignore": "Игнориши", - "@ignore": { - "type": "text", - "placeholders": {} - }, - "ignoredUsers": "Игнорисани корисници", - "@ignoredUsers": { - "type": "text", - "placeholders": {} - }, - "iHaveClickedOnLink": "Кликнуо сам на везу", - "@iHaveClickedOnLink": { - "type": "text", - "placeholders": {} - }, - "incorrectPassphraseOrKey": "Неисправна фраза или кључ опоравка", - "@incorrectPassphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "inoffensive": "Није увредљив", - "@inoffensive": { - "type": "text", - "placeholders": {} - }, - "inviteContact": "Позивање особа", - "@inviteContact": { - "type": "text", - "placeholders": {} - }, - "inviteContactToGroup": "Позови особу у групу {groupName}", - "@inviteContactToGroup": { - "type": "text", - "placeholders": { - "groupName": {} - } - }, - "invited": "Позван", - "@invited": { - "type": "text", - "placeholders": {} - }, - "invitedUser": "{username} позва корисника {targetName}", - "@invitedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "invitedUsersOnly": "само позвани корисници", - "@invitedUsersOnly": { - "type": "text", - "placeholders": {} - }, - "inviteForMe": "Позивнице за мене", - "@inviteForMe": { - "type": "text", - "placeholders": {} - }, - "inviteText": "{username} вас позива у FluffyChat. \n1. Инсталирајте FluffyChat: https://fluffychat.im \n2. Региструјте се или пријавите \n3. Отворите везу позивнице: {link}", - "@inviteText": { - "type": "text", - "placeholders": { - "username": {}, - "link": {} - } - }, - "isTyping": "куца…", - "@isTyping": { - "type": "text", - "placeholders": {} - }, - "joinedTheChat": "{username} се придружи ћаскању", - "@joinedTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "joinRoom": "Придружи се соби", - "@joinRoom": { - "type": "text", - "placeholders": {} - }, - "kicked": "{username} избаци корисника {targetName}", - "@kicked": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickedAndBanned": "{username} избаци и забрани корисника {targetName}", - "@kickedAndBanned": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "kickFromChat": "Избаци из ћаскања", - "@kickFromChat": { - "type": "text", - "placeholders": {} - }, - "lastActiveAgo": "Последња активност: {localizedTimeShort}", - "@lastActiveAgo": { - "type": "text", - "placeholders": { - "localizedTimeShort": {} - } - }, - "leave": "Напусти", - "@leave": { - "type": "text", - "placeholders": {} - }, - "leftTheChat": "Напусти ћаскање", - "@leftTheChat": { - "type": "text", - "placeholders": {} - }, - "license": "Лиценца", - "@license": { - "type": "text", - "placeholders": {} - }, - "lightTheme": "светли", - "@lightTheme": { - "type": "text", - "placeholders": {} - }, - "loadCountMoreParticipants": "Учитај још {count} учесника", - "@loadCountMoreParticipants": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "loadingPleaseWait": "Учитавам… Сачекајте.", - "@loadingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "loadMore": "Учитај још…", - "@loadMore": { - "type": "text", - "placeholders": {} - }, - "login": "Пријава", - "@login": { - "type": "text", - "placeholders": {} - }, - "logInTo": "Пријава на {homeserver}", - "@logInTo": { - "type": "text", - "placeholders": { - "homeserver": {} - } - }, - "logout": "Одјава", - "@logout": { - "type": "text", - "placeholders": {} - }, - "memberChanges": "Измене чланова", - "@memberChanges": { - "type": "text", - "placeholders": {} - }, - "mention": "Спомени", - "@mention": { - "type": "text", - "placeholders": {} - }, - "messages": "Поруке", - "@messages": { - "type": "text", - "placeholders": {} - }, - "moderator": "Модератор", - "@moderator": { - "type": "text", - "placeholders": {} - }, - "muteChat": "Ућуткај ћаскање", - "@muteChat": { - "type": "text", - "placeholders": {} - }, - "needPantalaimonWarning": "За сада, потребан је Пантелејмон (Pantalaimon) да бисте користили шифровање с краја на крај.", - "@needPantalaimonWarning": { - "type": "text", - "placeholders": {} - }, - "newChat": "Ново ћаскање", - "@newChat": { - "type": "text", - "placeholders": {} - }, - "newMessageInFluffyChat": "Нова порука — FluffyChat", - "@newMessageInFluffyChat": { - "type": "text", - "placeholders": {} - }, - "newVerificationRequest": "Нови захтев за верификацију!", - "@newVerificationRequest": { - "type": "text", - "placeholders": {} - }, - "next": "Следеће", - "@next": { - "type": "text", - "placeholders": {} - }, - "no": "Не", - "@no": { - "type": "text", - "placeholders": {} - }, - "noConnectionToTheServer": "Нема везе са сервером", - "@noConnectionToTheServer": { - "type": "text", - "placeholders": {} - }, - "noEmotesFound": "Нема емотија. 😕", - "@noEmotesFound": { - "type": "text", - "placeholders": {} - }, - "noEncryptionForPublicRooms": "Шифровање се може активирати након што соба престане да буде јавно доступна.", - "@noEncryptionForPublicRooms": { - "type": "text", - "placeholders": {} - }, - "noGoogleServicesWarning": "Чини се да немате Гугл услуге на телефону. То је добра одлука за вашу приватност! Да би се протурале нотификације у FluffyChat, препоручујемо коришћење https://microg.org/ или https://unifiedpush.org/", - "@noGoogleServicesWarning": { - "type": "text", - "placeholders": {} - }, - "none": "Ништа", - "@none": { - "type": "text", - "placeholders": {} - }, - "noPasswordRecoveryDescription": "Још нисте одредили начин за опоравак лозинке.", - "@noPasswordRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "noPermission": "Нема дозвола", - "@noPermission": { - "type": "text", - "placeholders": {} - }, - "noRoomsFound": "Нисам нашао собе…", - "@noRoomsFound": { - "type": "text", - "placeholders": {} - }, - "notifications": "Обавештења", - "@notifications": { - "type": "text", - "placeholders": {} - }, - "notificationsEnabledForThisAccount": "Обавештења укључена за овај налог", - "@notificationsEnabledForThisAccount": { - "type": "text", - "placeholders": {} - }, - "numUsersTyping": "{count} корисника куца…", - "@numUsersTyping": { - "type": "text", - "placeholders": { - "count": {} - } - }, - "offensive": "Увредљив", - "@offensive": { - "type": "text", - "placeholders": {} - }, - "offline": "Ван везе", - "@offline": { - "type": "text", - "placeholders": {} - }, - "ok": "у реду", - "@ok": { - "type": "text", - "placeholders": {} - }, - "online": "На вези", - "@online": { - "type": "text", - "placeholders": {} - }, - "onlineKeyBackupEnabled": "Резерва кључева на мрежи је укључена", - "@onlineKeyBackupEnabled": { - "type": "text", - "placeholders": {} - }, - "oopsPushError": "Нажалост, дошло је до грешке при подешавању дотурања обавештења.", - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "oopsSomethingWentWrong": "Нешто је пошло наопако…", - "@oopsSomethingWentWrong": { - "type": "text", - "placeholders": {} - }, - "openAppToReadMessages": "Отворите апликацију да прочитате поруке", - "@openAppToReadMessages": { - "type": "text", - "placeholders": {} - }, - "openCamera": "Отвори камеру", - "@openCamera": { - "type": "text", - "placeholders": {} - }, - "or": "или", - "@or": { - "type": "text", - "placeholders": {} - }, - "participant": "Учесник", - "@participant": { - "type": "text", - "placeholders": {} - }, - "passphraseOrKey": "фраза или кључ опоравка", - "@passphraseOrKey": { - "type": "text", - "placeholders": {} - }, - "password": "Лозинка", - "@password": { - "type": "text", - "placeholders": {} - }, - "passwordForgotten": "Заборављена лозинка", - "@passwordForgotten": { - "type": "text", - "placeholders": {} - }, - "passwordHasBeenChanged": "Лозинка је промењена", - "@passwordHasBeenChanged": { - "type": "text", - "placeholders": {} - }, - "passwordRecovery": "Опоравак лозинке", - "@passwordRecovery": { - "type": "text", - "placeholders": {} - }, - "people": "Људи", - "@people": { - "type": "text", - "placeholders": {} - }, - "pickImage": "Избор слике", - "@pickImage": { - "type": "text", - "placeholders": {} - }, - "pin": "Закачи", - "@pin": { - "type": "text", - "placeholders": {} - }, - "play": "Пусти {fileName}", - "@play": { - "type": "text", - "placeholders": { - "fileName": {} - } - }, - "pleaseChoose": "Изаберите", - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "pleaseChooseAPasscode": "Изаберите код за пролаз", - "@pleaseChooseAPasscode": { - "type": "text", - "placeholders": {} - }, - "pleaseClickOnLink": "Кликните на везу у примљеној е-пошти па наставите.", - "@pleaseClickOnLink": { - "type": "text", - "placeholders": {} - }, - "pleaseEnter4Digits": "Унесите 4 цифре или оставите празно да не закључавате апликацију.", - "@pleaseEnter4Digits": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPassword": "Унесите своју лозинку", - "@pleaseEnterYourPassword": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourPin": "Унесите свој пин", - "@pleaseEnterYourPin": { - "type": "text", - "placeholders": {} - }, - "pleaseEnterYourUsername": "Унесите своје корисничко име", - "@pleaseEnterYourUsername": { - "type": "text", - "placeholders": {} - }, - "pleaseFollowInstructionsOnWeb": "Испратите упутства на веб сајту и тапните на „Следеће“.", - "@pleaseFollowInstructionsOnWeb": { - "type": "text", - "placeholders": {} - }, - "privacy": "Приватност", - "@privacy": { - "type": "text", - "placeholders": {} - }, - "publicRooms": "Јавне собе", - "@publicRooms": { - "type": "text", - "placeholders": {} - }, - "pushRules": "Правила протурања", - "@pushRules": { - "type": "text", - "placeholders": {} - }, - "reason": "Разлог", - "@reason": { - "type": "text", - "placeholders": {} - }, - "recording": "Снимам", - "@recording": { - "type": "text", - "placeholders": {} - }, - "redactedAnEvent": "{username} редигова догађај", - "@redactedAnEvent": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "redactMessage": "Редигуј поруку", - "@redactMessage": { - "type": "text", - "placeholders": {} - }, - "register": "Регистрација", - "@register": { - "type": "text", - "placeholders": {} - }, - "reject": "Одбиј", - "@reject": { - "type": "text", - "placeholders": {} - }, - "rejectedTheInvitation": "{username} одби позивницу", - "@rejectedTheInvitation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "rejoin": "Поново се придружи", - "@rejoin": { - "type": "text", - "placeholders": {} - }, - "remove": "Уклони", - "@remove": { - "type": "text", - "placeholders": {} - }, - "removeAllOtherDevices": "Уклони све остале уређаје", - "@removeAllOtherDevices": { - "type": "text", - "placeholders": {} - }, - "removedBy": "Уклонио корисник {username}", - "@removedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "removeDevice": "Уклони уређај", - "@removeDevice": { - "type": "text", - "placeholders": {} - }, - "unbanFromChat": "Уклони изгнанство", - "@unbanFromChat": { - "type": "text", - "placeholders": {} - }, - "removeYourAvatar": "Уклоните свој аватар", - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "renderRichContent": "Приказуј обогаћен садржај поруке", - "@renderRichContent": { - "type": "text", - "placeholders": {} - }, - "replaceRoomWithNewerVersion": "Замени собу новијом верзијом", - "@replaceRoomWithNewerVersion": { - "type": "text", - "placeholders": {} - }, - "reply": "Одговори", - "@reply": { - "type": "text", - "placeholders": {} - }, - "reportMessage": "Пријави поруку", - "@reportMessage": { - "type": "text", - "placeholders": {} - }, - "requestPermission": "Затражи дозволу", - "@requestPermission": { - "type": "text", - "placeholders": {} - }, - "roomHasBeenUpgraded": "Соба је надограђена", - "@roomHasBeenUpgraded": { - "type": "text", - "placeholders": {} - }, - "roomVersion": "Верзија собе", - "@roomVersion": { - "type": "text", - "placeholders": {} - }, - "search": "Претражи", - "@search": { - "type": "text", - "placeholders": {} - }, - "security": "Безбедност", - "@security": { - "type": "text", - "placeholders": {} - }, - "seenByUser": "{username} прегледа", - "@seenByUser": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "send": "Пошаљи", - "@send": { - "type": "text", - "placeholders": {} - }, - "sendAMessage": "Пошаљи поруку", - "@sendAMessage": { - "type": "text", - "placeholders": {} - }, - "sendAudio": "Пошаљи аудио", - "@sendAudio": { - "type": "text", - "placeholders": {} - }, - "sendFile": "Пошаљи фајл", - "@sendFile": { - "type": "text", - "placeholders": {} - }, - "sendImage": "Пошаљи слику", - "@sendImage": { - "type": "text", - "placeholders": {} - }, - "sendMessages": "Слање порука", - "@sendMessages": { - "type": "text", - "placeholders": {} - }, - "sendOriginal": "Пошаљи оригинал", - "@sendOriginal": { - "type": "text", - "placeholders": {} - }, - "sendVideo": "Пошаљи видео", - "@sendVideo": { - "type": "text", - "placeholders": {} - }, - "sentAFile": "{username} посла фајл", - "@sentAFile": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAnAudio": "{username} посла аудио", - "@sentAnAudio": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAPicture": "{username} посла слику", - "@sentAPicture": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentASticker": "{username} посла налепницу", - "@sentASticker": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentAVideo": "{username} посла видео", - "@sentAVideo": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "sentCallInformations": "{senderName} посла податке о позиву", - "@sentCallInformations": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "setAsCanonicalAlias": "Постави као главни алијас", - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "setCustomEmotes": "постави посебне емотије", - "@setCustomEmotes": { - "type": "text", - "placeholders": {} - }, - "setInvitationLink": "Поставља везу позивнице", - "@setInvitationLink": { - "type": "text", - "placeholders": {} - }, - "setPermissionsLevel": "Одреди ниво дозволе", - "@setPermissionsLevel": { - "type": "text", - "placeholders": {} - }, - "setStatus": "Постави статус", - "@setStatus": { - "type": "text", - "placeholders": {} - }, - "settings": "Поставке", - "@settings": { - "type": "text", - "placeholders": {} - }, - "share": "Подели", - "@share": { - "type": "text", - "placeholders": {} - }, - "sharedTheLocation": "{username} подели локацију", - "@sharedTheLocation": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "showPassword": "Прикажи лозинку", - "@showPassword": { - "type": "text", - "placeholders": {} - }, - "singlesignon": "Јединствена пријава", - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "skip": "Прескочи", - "@skip": { - "type": "text", - "placeholders": {} - }, - "sourceCode": "Изворни код", - "@sourceCode": { - "type": "text", - "placeholders": {} - }, - "startedACall": "{senderName} започе позив", - "@startedACall": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "status": "Стање", - "@status": { - "type": "text", - "placeholders": {} - }, - "statusExampleMessage": "Како сте данас?", - "@statusExampleMessage": { - "type": "text", - "placeholders": {} - }, - "submit": "Пошаљи", - "@submit": { - "type": "text", - "placeholders": {} - }, - "systemTheme": "системски", - "@systemTheme": { - "type": "text", - "placeholders": {} - }, - "theyDontMatch": "Не поклапају се", - "@theyDontMatch": { - "type": "text", - "placeholders": {} - }, - "theyMatch": "Поклапају се", - "@theyMatch": { - "type": "text", - "placeholders": {} - }, - "title": "FluffyChat", - "@title": { - "description": "Title for the application", - "type": "text", - "placeholders": {} - }, - "toggleFavorite": "Мењај омиљеност", - "@toggleFavorite": { - "type": "text", - "placeholders": {} - }, - "toggleMuted": "Мењај ућутканост", - "@toggleMuted": { - "type": "text", - "placeholders": {} - }, - "toggleUnread": "Означи не/прочитано", - "@toggleUnread": { - "type": "text", - "placeholders": {} - }, - "tooManyRequestsWarning": "Превише упита. Покушајте касније!", - "@tooManyRequestsWarning": { - "type": "text", - "placeholders": {} - }, - "transferFromAnotherDevice": "Пренос са другог уређаја", - "@transferFromAnotherDevice": { - "type": "text", - "placeholders": {} - }, - "tryToSendAgain": "Покушај слање поново", - "@tryToSendAgain": { - "type": "text", - "placeholders": {} - }, - "unavailable": "Недоступно", - "@unavailable": { - "type": "text", - "placeholders": {} - }, - "unbannedUser": "{username} одблокира корисника {targetName}", - "@unbannedUser": { - "type": "text", - "placeholders": { - "username": {}, - "targetName": {} - } - }, - "unblockDevice": "Одблокирај уређај", - "@unblockDevice": { - "type": "text", - "placeholders": {} - }, - "unknownDevice": "Непознат уређај", - "@unknownDevice": { - "type": "text", - "placeholders": {} - }, - "unknownEncryptionAlgorithm": "Непознат алгоритам шифровања", - "@unknownEncryptionAlgorithm": { - "type": "text", - "placeholders": {} - }, - "unknownEvent": "Непознат догађај „{type}“", - "@unknownEvent": { - "type": "text", - "placeholders": { - "type": {} - } - }, - "unmuteChat": "Врати обавештења", - "@unmuteChat": { - "type": "text", - "placeholders": {} - }, - "unpin": "Откачи", - "@unpin": { - "type": "text", - "placeholders": {} - }, - "unreadChats": "{unreadCount, plural, other{непрочитаних ћаскања: {unreadCount}}}", - "@unreadChats": { - "type": "text", - "placeholders": { - "unreadCount": {} - } - }, - "userAndOthersAreTyping": "{username} и {count} корисника куцају…", - "@userAndOthersAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "count": {} - } - }, - "userAndUserAreTyping": "{username} и {username2} куцају…", - "@userAndUserAreTyping": { - "type": "text", - "placeholders": { - "username": {}, - "username2": {} - } - }, - "userIsTyping": "{username} куца…", - "@userIsTyping": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "userLeftTheChat": "{username} напусти ћаскање", - "@userLeftTheChat": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "username": "Корисничко име", - "@username": { - "type": "text", - "placeholders": {} - }, - "userSentUnknownEvent": "{username} посла {type} догађај", - "@userSentUnknownEvent": { - "type": "text", - "placeholders": { - "username": {}, - "type": {} - } - }, - "verified": "Оверен", - "@verified": { - "type": "text", - "placeholders": {} - }, - "verify": "Верификуј", - "@verify": { - "type": "text", - "placeholders": {} - }, - "verifyStart": "Покрени верификацију", - "@verifyStart": { - "type": "text", - "placeholders": {} - }, - "verifySuccess": "Успешно сте верификовали!", - "@verifySuccess": { - "type": "text", - "placeholders": {} - }, - "verifyTitle": "Верификујем други налог", - "@verifyTitle": { - "type": "text", - "placeholders": {} - }, - "videoCall": "Видео позив", - "@videoCall": { - "type": "text", - "placeholders": {} - }, - "visibilityOfTheChatHistory": "Одреди видљивост историје", - "@visibilityOfTheChatHistory": { - "type": "text", - "placeholders": {} - }, - "visibleForAllParticipants": "видљиво свим учесницима", - "@visibleForAllParticipants": { - "type": "text", - "placeholders": {} - }, - "visibleForEveryone": "видљиво свима", - "@visibleForEveryone": { - "type": "text", - "placeholders": {} - }, - "voiceMessage": "Гласовна порука", - "@voiceMessage": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerAcceptRequest": "Чекам да саговорник прихвати захтев…", - "@waitingPartnerAcceptRequest": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerEmoji": "Чекам да саговорник прихвати емоџије…", - "@waitingPartnerEmoji": { - "type": "text", - "placeholders": {} - }, - "waitingPartnerNumbers": "Чекам да саговорник прихвати бројеве…", - "@waitingPartnerNumbers": { - "type": "text", - "placeholders": {} - }, - "wallpaper": "Тапета", - "@wallpaper": { - "type": "text", - "placeholders": {} - }, - "warning": "Упозорење!", - "@warning": { - "type": "text", - "placeholders": {} - }, - "weSentYouAnEmail": "Послали смо вам е-пошту", - "@weSentYouAnEmail": { - "type": "text", - "placeholders": {} - }, - "whoCanPerformWhichAction": "ко може шта да ради", - "@whoCanPerformWhichAction": { - "type": "text", - "placeholders": {} - }, - "whoIsAllowedToJoinThisGroup": "Ко може да се придружи групи", - "@whoIsAllowedToJoinThisGroup": { - "type": "text", - "placeholders": {} - }, - "whyDoYouWantToReportThis": "Зашто желите ово да пријавите?", - "@whyDoYouWantToReportThis": { - "type": "text", - "placeholders": {} - }, - "wipeChatBackup": "Да обришем резервну копију како би направио нови сигурносни кључ?", - "@wipeChatBackup": { - "type": "text", - "placeholders": {} - }, - "withTheseAddressesRecoveryDescription": "Са овим адресама можете опоравити своју лозинку.", - "@withTheseAddressesRecoveryDescription": { - "type": "text", - "placeholders": {} - }, - "writeAMessage": "напишите поруку…", - "@writeAMessage": { - "type": "text", - "placeholders": {} - }, - "yes": "Да", - "@yes": { - "type": "text", - "placeholders": {} - }, - "you": "Ви", - "@you": { - "type": "text", - "placeholders": {} - }, - "youAreNoLongerParticipatingInThisChat": "Више не учествујете у овом ћаскању", - "@youAreNoLongerParticipatingInThisChat": { - "type": "text", - "placeholders": {} - }, - "youHaveBeenBannedFromThisChat": "Забрањено вам је ово ћаскање", - "@youHaveBeenBannedFromThisChat": { - "type": "text", - "placeholders": {} - }, - "yourPublicKey": "Ваш јавни кључ", - "@yourPublicKey": { - "type": "text", - "placeholders": {} - }, - "@hugContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "@commandHint_cuddle": {}, - "@widgetVideo": {}, - "@dismiss": {}, - "@reportErrorDescription": {}, - "@addAccount": {}, - "@chatHasBeenAddedToThisSpace": {}, - "@unsupportedAndroidVersion": {}, - "@widgetJitsi": {}, - "@messageType": {}, - "@indexedDbErrorLong": {}, - "@oneClientLoggedOut": {}, - "@startFirstChat": {}, - "@callingAccount": {}, - "@setColorTheme": {}, - "@nextAccount": {}, - "@commandHint_create": { - "type": "text", - "description": "Usage hint for the command /create" - }, - "@allSpaces": {}, - "@supposedMxid": { - "type": "text", - "placeholders": { - "mxid": {} - } - }, - "@user": {}, - "@youAcceptedTheInvitation": {}, - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "@banUserDescription": {}, - "@widgetEtherpad": {}, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "@unbanUserDescription": {}, - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "@sendOnEnter": {}, - "@youRejectedTheInvitation": {}, - "@otherCallingPermissions": {}, - "@messagesStyle": {}, - "@link": {}, - "@widgetUrlError": {}, - "@emailOrUsername": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@enterSpace": {}, - "@encryptThisChat": {}, - "@previousAccount": {}, - "@reopenChat": {}, - "@pleaseEnterRecoveryKey": {}, - "@widgetNameError": {}, - "@addToBundle": {}, - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "@addWidget": {}, - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "@noKeyForThisMessage": {}, - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "@commandHint_markasgroup": {}, - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "@hydrateTor": {}, - "@pushNotificationsNotAvailable": {}, - "@storeInAppleKeyChain": {}, - "@hydrate": {}, - "@invalidServerName": {}, - "@chatPermissions": {}, - "@cantOpenUri": { - "type": "text", - "placeholders": { - "uri": {} - } - }, - "@sender": {}, - "@storeInAndroidKeystore": {}, - "@signInWithPassword": {}, - "@makeAdminDescription": {}, - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "@commandHint_clearcache": { - "type": "text", - "description": "Usage hint for the command /clearcache" - }, - "@saveKeyManuallyDescription": {}, - "@editBundlesForAccount": {}, - "@whyIsThisMessageEncrypted": {}, - "@setChatDescription": {}, - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "@importFromZipFile": {}, - "@dehydrateWarning": {}, - "@noOtherDevicesFound": {}, - "@yourChatBackupHasBeenSetUp": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@videoCallsBetaWarning": {}, - "@autoplayImages": { - "type": "text", - "placeholder": {} - }, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@fileIsTooBigForServer": {}, - "@homeserver": {}, - "@repeatPassword": {}, - "@callingPermissions": {}, - "@readUpToHere": {}, - "@start": {}, - "@unlockOldMessages": {}, - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@optionalRedactReason": {}, - "@dehydrate": {}, - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "@sendAsText": { - "type": "text" - }, - "@archiveRoomDescription": {}, - "@exportEmotePack": {}, - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@commandInvalid": { - "type": "text" - }, - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "@experimentalVideoCalls": {}, - "@pleaseEnterRecoveryKeyDescription": {}, - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "@appearOnTopDetails": {}, - "@enterRoom": {}, - "@allChats": { - "type": "text", - "placeholders": {} - }, - "@reportUser": {}, - "@confirmEventUnpin": {}, - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "@addToSpace": {}, - "@commandMissing": { - "type": "text", - "placeholders": { - "command": {} - }, - "description": "State that {command} is not a valid /command." - }, - "@redactMessageDescription": {}, - "@recoveryKey": {}, - "@commandHint_discardsession": { - "type": "text", - "description": "Usage hint for the command /discardsession" - }, - "@invalidInput": {}, - "@dehydrateTorLong": {}, - "@doNotShowAgain": {}, - "@report": {}, - "@unverified": {}, - "@serverRequiresEmail": {}, - "@hideUnimportantStateEvents": {}, - "@screenSharingTitle": {}, - "@widgetCustom": {}, - "@addToSpaceDescription": {}, - "@googlyEyesContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@youBannedUser": { - "placeholders": { - "user": {} - } - }, - "@addChatDescription": {}, - "@commandHint_myroomavatar": { - "type": "text", - "description": "Usage hint for the command /myroomavatar" - }, - "@hasKnocked": { - "placeholders": { - "user": {} - } - }, - "@publish": {}, - "@openLinkInBrowser": {}, - "@messageInfo": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, - "@wrongPinEntered": { - "type": "text", - "placeholders": { - "seconds": {} - } - }, - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@foregroundServiceRunning": {}, - "@voiceCall": {}, - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", - "placeholders": { - "oldDisplayName": {} - } - }, - "@noChatDescriptionYet": {}, - "@removeFromBundle": {}, - "@confirmMatrixId": {}, - "@learnMore": {}, - "@notAnImage": {}, - "@users": {}, - "@openGallery": {}, - "@chatDescriptionHasBeenChanged": {}, - "@newGroup": {}, - "@bundleName": {}, - "@dehydrateTor": {}, - "@removeFromSpace": {}, - "@roomUpgradeDescription": {}, - "@scanQrCode": {}, - "@pleaseEnterANumber": {}, - "@youKicked": { - "placeholders": { - "user": {} - } - }, - "@profileNotFound": {}, - "@jump": {}, - "@reactedWith": { - "type": "text", - "placeholders": { - "sender": {}, - "reaction": {} - } - }, - "@sorryThatsNotPossible": {}, - "@videoWithSize": { - "type": "text", - "placeholders": { - "size": {} - } - }, - "@shareInviteLink": {}, - "@commandHint_markasdm": {}, - "@recoveryKeyLost": {}, - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@deviceKeys": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@youJoinedTheChat": {}, - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "@markAsRead": {}, - "@widgetName": {}, - "@errorAddingWidget": {}, - "@commandHint_dm": { - "type": "text", - "description": "Usage hint for the command /dm" - }, - "@commandHint_hug": {}, - "@replace": {}, - "@youUnbannedUser": { - "placeholders": { - "user": {} - } - }, - "@newSpace": {}, - "@emojis": {}, - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@hydrateTorLong": {}, - "@time": {}, - "@custom": {}, - "@noBackupWarning": {}, - "@storeInSecureStorageDescription": {}, - "@openChat": {}, - "@kickUserDescription": {}, - "@importNow": {}, - "@pinMessage": {}, - "@invite": {}, - "@enableMultiAccounts": {}, - "@indexedDbErrorTitle": {}, - "@unsupportedAndroidVersionLong": {}, - "@storeSecurlyOnThisDevice": {}, - "@screenSharingDetail": {}, - "@placeCall": {} -} \ No newline at end of file + "@@last_modified": "2021-08-14 12:41:09.857024", + "about": "О програму", + "@about": { + "type": "text", + "placeholders": {} + }, + "accept": "Прихвати", + "@accept": { + "type": "text", + "placeholders": {} + }, + "acceptedTheInvitation": "{username} прихвата позивницу", + "@acceptedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "account": "Налог", + "@account": { + "type": "text", + "placeholders": {} + }, + "activatedEndToEndEncryption": "{username} укључи шифровање с краја на крај", + "@activatedEndToEndEncryption": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "addEmail": "Додај е-адресу", + "@addEmail": { + "type": "text", + "placeholders": {} + }, + "admin": "Админ", + "@admin": { + "type": "text", + "placeholders": {} + }, + "alias": "алијас", + "@alias": { + "type": "text", + "placeholders": {} + }, + "all": "Сви", + "@all": { + "type": "text", + "placeholders": {} + }, + "answeredTheCall": "{senderName} одговори на позив", + "@answeredTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "anyoneCanJoin": "свако може да се придружи", + "@anyoneCanJoin": { + "type": "text", + "placeholders": {} + }, + "appLock": "Закључавање апликације", + "@appLock": { + "type": "text", + "placeholders": {} + }, + "archive": "Архива", + "@archive": { + "type": "text", + "placeholders": {} + }, + "areGuestsAllowedToJoin": "Да ли је гостима дозвољен приступ", + "@areGuestsAllowedToJoin": { + "type": "text", + "placeholders": {} + }, + "areYouSure": "Сигурни сте?", + "@areYouSure": { + "type": "text", + "placeholders": {} + }, + "areYouSureYouWantToLogout": "Заиста желите да се одјавите?", + "@areYouSureYouWantToLogout": { + "type": "text", + "placeholders": {} + }, + "askSSSSSign": "Да бисте могли да пријавите другу особу, унесите своју безбедносну фразу или кључ опоравка.", + "@askSSSSSign": { + "type": "text", + "placeholders": {} + }, + "askVerificationRequest": "Прихватате ли захтев за верификацију од корисника {username}?", + "@askVerificationRequest": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "badServerLoginTypesException": "Домаћи сервер подржава начине пријаве:\n{serverVersions}\nали ова апликација подржава само:\n{supportedVersions}", + "@badServerLoginTypesException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "badServerVersionsException": "Домаћи сервер подржава верзије:\n{serverVersions}\nали ова апликација подржава само {supportedVersions}", + "@badServerVersionsException": { + "type": "text", + "placeholders": { + "serverVersions": {}, + "supportedVersions": {} + } + }, + "banFromChat": "Забрани у ћаскању", + "@banFromChat": { + "type": "text", + "placeholders": {} + }, + "banned": "Забрањен", + "@banned": { + "type": "text", + "placeholders": {} + }, + "bannedUser": "{username} забрани корисника {targetName}", + "@bannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "blockDevice": "Блокирај уређај", + "@blockDevice": { + "type": "text", + "placeholders": {} + }, + "blocked": "Блокиран", + "@blocked": { + "type": "text", + "placeholders": {} + }, + "botMessages": "Поруке Бота", + "@botMessages": { + "type": "text", + "placeholders": {} + }, + "cancel": "Откажи", + "@cancel": { + "type": "text", + "placeholders": {} + }, + "changeDeviceName": "Промени назив уређаја", + "@changeDeviceName": { + "type": "text", + "placeholders": {} + }, + "changedTheChatAvatar": "{username} промени аватар ћаскања", + "@changedTheChatAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheChatDescriptionTo": "{username} промени опис ћаскања у: „{description}“", + "@changedTheChatDescriptionTo": { + "type": "text", + "placeholders": { + "username": {}, + "description": {} + } + }, + "changedTheChatNameTo": "{username} промени назив ћаскања у: „{chatname}“", + "@changedTheChatNameTo": { + "type": "text", + "placeholders": { + "username": {}, + "chatname": {} + } + }, + "changedTheChatPermissions": "{username} измени дозволе ћаскања", + "@changedTheChatPermissions": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheDisplaynameTo": "{username} промени приказно име на: „{displayname}“", + "@changedTheDisplaynameTo": { + "type": "text", + "placeholders": { + "username": {}, + "displayname": {} + } + }, + "changedTheGuestAccessRules": "{username} измени правила за приступ гостију", + "@changedTheGuestAccessRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheGuestAccessRulesTo": "{username} измени правила за приступ гостију на: {rules}", + "@changedTheGuestAccessRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheHistoryVisibility": "{username} измени видљивост историје", + "@changedTheHistoryVisibility": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheHistoryVisibilityTo": "{username} измени видљивост историје на: {rules}", + "@changedTheHistoryVisibilityTo": { + "type": "text", + "placeholders": { + "username": {}, + "rules": {} + } + }, + "changedTheJoinRules": "{username} измени правила приступања", + "@changedTheJoinRules": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheJoinRulesTo": "{username} измени правила приступања на: {joinRules}", + "@changedTheJoinRulesTo": { + "type": "text", + "placeholders": { + "username": {}, + "joinRules": {} + } + }, + "changedTheProfileAvatar": "{username} измени свој аватар", + "@changedTheProfileAvatar": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomAliases": "{username} измени алијас собе", + "@changedTheRoomAliases": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changedTheRoomInvitationLink": "{username} измени везу позивнице", + "@changedTheRoomInvitationLink": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "changePassword": "Измени лозинку", + "@changePassword": { + "type": "text", + "placeholders": {} + }, + "changeTheHomeserver": "Промени домаћи сервер", + "@changeTheHomeserver": { + "type": "text", + "placeholders": {} + }, + "changeTheme": "Измените изглед", + "@changeTheme": { + "type": "text", + "placeholders": {} + }, + "changeTheNameOfTheGroup": "Измени назив групе", + "@changeTheNameOfTheGroup": { + "type": "text", + "placeholders": {} + }, + "changeYourAvatar": "Измените свој аватар", + "@changeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "channelCorruptedDecryptError": "Шифровање је покварено", + "@channelCorruptedDecryptError": { + "type": "text", + "placeholders": {} + }, + "chat": "Ћаскање", + "@chat": { + "type": "text", + "placeholders": {} + }, + "chatBackup": "Копија ћаскања", + "@chatBackup": { + "type": "text", + "placeholders": {} + }, + "chatBackupDescription": "Ваша резервна копија ћаскања је обезбеђена кључем. Немојте да га изгубите.", + "@chatBackupDescription": { + "type": "text", + "placeholders": {} + }, + "chatDetails": "Детаљи ћаскања", + "@chatDetails": { + "type": "text", + "placeholders": {} + }, + "chats": "Ћаскања", + "@chats": { + "type": "text", + "placeholders": {} + }, + "chooseAStrongPassword": "Изаберите јаку лозинку", + "@chooseAStrongPassword": { + "type": "text", + "placeholders": {} + }, + "clearArchive": "Очисти архиву", + "@clearArchive": {}, + "close": "Затвори", + "@close": { + "type": "text", + "placeholders": {} + }, + "commandHint_ban": "Блокирај задатог корисника за ову собу", + "@commandHint_ban": { + "type": "text", + "description": "Usage hint for the command /ban" + }, + "commandHint_html": "Шаљи ХТМЛ обликован текст", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_invite": "Позови задатог корисника у собу", + "@commandHint_invite": { + "type": "text", + "description": "Usage hint for the command /invite" + }, + "commandHint_join": "Придружи се наведеној соби", + "@commandHint_join": { + "type": "text", + "description": "Usage hint for the command /join" + }, + "commandHint_kick": "Уклони задатог корисника из собе", + "@commandHint_kick": { + "type": "text", + "description": "Usage hint for the command /kick" + }, + "commandHint_leave": "Напусти ову собу", + "@commandHint_leave": { + "type": "text", + "description": "Usage hint for the command /leave" + }, + "commandHint_me": "Опишите себе", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "commandHint_myroomnick": "Поставља ваш надимак за ову собу", + "@commandHint_myroomnick": { + "type": "text", + "description": "Usage hint for the command /myroomnick" + }, + "commandHint_op": "Подеси ниво задатог корисника (подразумевано: 50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "commandHint_plain": "Шаљи неформатиран текст", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_react": "Шаљи одговор као реакцију", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "commandHint_send": "Пошаљи текст", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "commandHint_unban": "Скини забрану задатом кориснику за ову собу", + "@commandHint_unban": { + "type": "text", + "description": "Usage hint for the command /unban" + }, + "compareEmojiMatch": "Упоредите и проверите да су емоџији идентични као на другом уређају:", + "@compareEmojiMatch": { + "type": "text", + "placeholders": {} + }, + "compareNumbersMatch": "Упоредите и проверите да су следећи бројеви идентични као на другом уређају:", + "@compareNumbersMatch": { + "type": "text", + "placeholders": {} + }, + "configureChat": "Подешавање ћаскања", + "@configureChat": { + "type": "text", + "placeholders": {} + }, + "confirm": "Потврди", + "@confirm": { + "type": "text", + "placeholders": {} + }, + "connect": "Повежи се", + "@connect": { + "type": "text", + "placeholders": {} + }, + "contactHasBeenInvitedToTheGroup": "Особа је позвана у групу", + "@contactHasBeenInvitedToTheGroup": { + "type": "text", + "placeholders": {} + }, + "containsDisplayName": "Садржи приказно име", + "@containsDisplayName": { + "type": "text", + "placeholders": {} + }, + "containsUserName": "Садржи корисничко име", + "@containsUserName": { + "type": "text", + "placeholders": {} + }, + "contentHasBeenReported": "Садржај је пријављен администраторима сервера", + "@contentHasBeenReported": { + "type": "text", + "placeholders": {} + }, + "copiedToClipboard": "Копирано у клипборд", + "@copiedToClipboard": { + "type": "text", + "placeholders": {} + }, + "copy": "Копирај", + "@copy": { + "type": "text", + "placeholders": {} + }, + "copyToClipboard": "Копирај у клипборд", + "@copyToClipboard": { + "type": "text", + "placeholders": {} + }, + "couldNotDecryptMessage": "Не могу да дешифрујем поруку: {error}", + "@couldNotDecryptMessage": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "countParticipants": "учесника: {count}", + "@countParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "create": "Направи", + "@create": { + "type": "text", + "placeholders": {} + }, + "createdTheChat": "{username} направи ћаскање", + "@createdTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "currentlyActive": "Тренутно активно", + "@currentlyActive": { + "type": "text", + "placeholders": {} + }, + "darkTheme": "тамни", + "@darkTheme": { + "type": "text", + "placeholders": {} + }, + "dateAndTimeOfDay": "{date}, {timeOfDay}", + "@dateAndTimeOfDay": { + "type": "text", + "placeholders": { + "date": {}, + "timeOfDay": {} + } + }, + "dateWithoutYear": "{day} {month}", + "@dateWithoutYear": { + "type": "text", + "placeholders": { + "month": {}, + "day": {} + } + }, + "dateWithYear": "{day} {month} {year}", + "@dateWithYear": { + "type": "text", + "placeholders": { + "year": {}, + "month": {}, + "day": {} + } + }, + "deactivateAccountWarning": "Ово ће деактивирати ваш кориснички налог. Не може се повратити! Сигурни сте?", + "@deactivateAccountWarning": { + "type": "text", + "placeholders": {} + }, + "defaultPermissionLevel": "Подразумевани ниво приступа", + "@defaultPermissionLevel": { + "type": "text", + "placeholders": {} + }, + "delete": "Обриши", + "@delete": { + "type": "text", + "placeholders": {} + }, + "deleteAccount": "Обриши налог", + "@deleteAccount": { + "type": "text", + "placeholders": {} + }, + "deleteMessage": "Брисање поруке", + "@deleteMessage": { + "type": "text", + "placeholders": {} + }, + "device": "Уређај", + "@device": { + "type": "text", + "placeholders": {} + }, + "deviceId": "ИД уређаја", + "@deviceId": { + "type": "text", + "placeholders": {} + }, + "devices": "Уређаји", + "@devices": { + "type": "text", + "placeholders": {} + }, + "directChats": "Директна ћаскања", + "@directChats": { + "type": "text", + "placeholders": {} + }, + "displaynameHasBeenChanged": "Име за приказ је измењено", + "@displaynameHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "downloadFile": "Преузми фајл", + "@downloadFile": { + "type": "text", + "placeholders": {} + }, + "edit": "Уреди", + "@edit": { + "type": "text", + "placeholders": {} + }, + "editBlockedServers": "Уреди блокиране сервере", + "@editBlockedServers": { + "type": "text", + "placeholders": {} + }, + "editDisplayname": "Уреди име за приказ", + "@editDisplayname": { + "type": "text", + "placeholders": {} + }, + "editRoomAliases": "Уреди алијасе собе", + "@editRoomAliases": { + "type": "text", + "placeholders": {} + }, + "editRoomAvatar": "Уређује аватар собе", + "@editRoomAvatar": { + "type": "text", + "placeholders": {} + }, + "emoteExists": "Емоти већ постоји!", + "@emoteExists": { + "type": "text", + "placeholders": {} + }, + "emoteInvalid": "Неисправна скраћеница за емоти!", + "@emoteInvalid": { + "type": "text", + "placeholders": {} + }, + "emotePacks": "Пакети емотија за собу", + "@emotePacks": { + "type": "text", + "placeholders": {} + }, + "emoteSettings": "Поставке емотија", + "@emoteSettings": { + "type": "text", + "placeholders": {} + }, + "emoteShortcode": "скраћеница", + "@emoteShortcode": { + "type": "text", + "placeholders": {} + }, + "emoteWarnNeedToPick": "Морате да изаберете скраћеницу и слику за емоти!", + "@emoteWarnNeedToPick": { + "type": "text", + "placeholders": {} + }, + "emptyChat": "празно ћаскање", + "@emptyChat": { + "type": "text", + "placeholders": {} + }, + "enableEmotesGlobally": "Глобално укључи пакет емотија", + "@enableEmotesGlobally": { + "type": "text", + "placeholders": {} + }, + "enableEncryption": "Укључује шифровање", + "@enableEncryption": { + "type": "text", + "placeholders": {} + }, + "enableEncryptionWarning": "Шифровање више нећете моћи да искључите. Сигурни сте?", + "@enableEncryptionWarning": { + "type": "text", + "placeholders": {} + }, + "encrypted": "Шифровано", + "@encrypted": { + "type": "text", + "placeholders": {} + }, + "encryption": "Шифровање", + "@encryption": { + "type": "text", + "placeholders": {} + }, + "encryptionNotEnabled": "Шифровање није укључено", + "@encryptionNotEnabled": { + "type": "text", + "placeholders": {} + }, + "endedTheCall": "{senderName} заврши позив", + "@endedTheCall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "enterAnEmailAddress": "Унесите адресу е-поште", + "@enterAnEmailAddress": { + "type": "text", + "placeholders": {} + }, + "enterYourHomeserver": "Унесите свој домаћи сервер", + "@enterYourHomeserver": { + "type": "text", + "placeholders": {} + }, + "everythingReady": "Све је спремно!", + "@everythingReady": { + "type": "text", + "placeholders": {} + }, + "extremeOffensive": "Екстремно увредљив", + "@extremeOffensive": { + "type": "text", + "placeholders": {} + }, + "fileName": "Назив фајла", + "@fileName": { + "type": "text", + "placeholders": {} + }, + "fluffychat": "FluffyChat", + "@fluffychat": { + "type": "text", + "placeholders": {} + }, + "fontSize": "Величина фонта", + "@fontSize": { + "type": "text", + "placeholders": {} + }, + "forward": "Напред", + "@forward": { + "type": "text", + "placeholders": {} + }, + "fromJoining": "од приступања", + "@fromJoining": { + "type": "text", + "placeholders": {} + }, + "fromTheInvitation": "од позивања", + "@fromTheInvitation": { + "type": "text", + "placeholders": {} + }, + "goToTheNewRoom": "Иди у нову собу", + "@goToTheNewRoom": { + "type": "text", + "placeholders": {} + }, + "group": "Група", + "@group": { + "type": "text", + "placeholders": {} + }, + "groupIsPublic": "Група је јавна", + "@groupIsPublic": { + "type": "text", + "placeholders": {} + }, + "groups": "Групе", + "@groups": { + "type": "text", + "placeholders": {} + }, + "groupWith": "Група са корисником {displayname}", + "@groupWith": { + "type": "text", + "placeholders": { + "displayname": {} + } + }, + "guestsAreForbidden": "гости су забрањени", + "@guestsAreForbidden": { + "type": "text", + "placeholders": {} + }, + "guestsCanJoin": "гости могу приступити", + "@guestsCanJoin": { + "type": "text", + "placeholders": {} + }, + "hasWithdrawnTheInvitationFor": "{username} поништи позивницу за корисника {targetName}", + "@hasWithdrawnTheInvitationFor": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "help": "Помоћ", + "@help": { + "type": "text", + "placeholders": {} + }, + "hideRedactedEvents": "Сакриј редиговане догађаје", + "@hideRedactedEvents": { + "type": "text", + "placeholders": {} + }, + "hideUnknownEvents": "Сакриј непознате догађаје", + "@hideUnknownEvents": { + "type": "text", + "placeholders": {} + }, + "howOffensiveIsThisContent": "Колико је увредљив овај садржај?", + "@howOffensiveIsThisContent": { + "type": "text", + "placeholders": {} + }, + "id": "ИД", + "@id": { + "type": "text", + "placeholders": {} + }, + "identity": "Идентитет", + "@identity": { + "type": "text", + "placeholders": {} + }, + "ignore": "Игнориши", + "@ignore": { + "type": "text", + "placeholders": {} + }, + "ignoredUsers": "Игнорисани корисници", + "@ignoredUsers": { + "type": "text", + "placeholders": {} + }, + "iHaveClickedOnLink": "Кликнуо сам на везу", + "@iHaveClickedOnLink": { + "type": "text", + "placeholders": {} + }, + "incorrectPassphraseOrKey": "Неисправна фраза или кључ опоравка", + "@incorrectPassphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "inoffensive": "Није увредљив", + "@inoffensive": { + "type": "text", + "placeholders": {} + }, + "inviteContact": "Позивање особа", + "@inviteContact": { + "type": "text", + "placeholders": {} + }, + "inviteContactToGroup": "Позови особу у групу {groupName}", + "@inviteContactToGroup": { + "type": "text", + "placeholders": { + "groupName": {} + } + }, + "invited": "Позван", + "@invited": { + "type": "text", + "placeholders": {} + }, + "invitedUser": "{username} позва корисника {targetName}", + "@invitedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "invitedUsersOnly": "само позвани корисници", + "@invitedUsersOnly": { + "type": "text", + "placeholders": {} + }, + "inviteForMe": "Позивнице за мене", + "@inviteForMe": { + "type": "text", + "placeholders": {} + }, + "inviteText": "{username} вас позива у FluffyChat. \n1. Инсталирајте FluffyChat: https://fluffychat.im \n2. Региструјте се или пријавите \n3. Отворите везу позивнице: {link}", + "@inviteText": { + "type": "text", + "placeholders": { + "username": {}, + "link": {} + } + }, + "isTyping": "куца…", + "@isTyping": { + "type": "text", + "placeholders": {} + }, + "joinedTheChat": "{username} се придружи ћаскању", + "@joinedTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "joinRoom": "Придружи се соби", + "@joinRoom": { + "type": "text", + "placeholders": {} + }, + "kicked": "{username} избаци корисника {targetName}", + "@kicked": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickedAndBanned": "{username} избаци и забрани корисника {targetName}", + "@kickedAndBanned": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "kickFromChat": "Избаци из ћаскања", + "@kickFromChat": { + "type": "text", + "placeholders": {} + }, + "lastActiveAgo": "Последња активност: {localizedTimeShort}", + "@lastActiveAgo": { + "type": "text", + "placeholders": { + "localizedTimeShort": {} + } + }, + "leave": "Напусти", + "@leave": { + "type": "text", + "placeholders": {} + }, + "leftTheChat": "Напусти ћаскање", + "@leftTheChat": { + "type": "text", + "placeholders": {} + }, + "license": "Лиценца", + "@license": { + "type": "text", + "placeholders": {} + }, + "lightTheme": "светли", + "@lightTheme": { + "type": "text", + "placeholders": {} + }, + "loadCountMoreParticipants": "Учитај још {count} учесника", + "@loadCountMoreParticipants": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "loadingPleaseWait": "Учитавам… Сачекајте.", + "@loadingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "loadMore": "Учитај још…", + "@loadMore": { + "type": "text", + "placeholders": {} + }, + "login": "Пријава", + "@login": { + "type": "text", + "placeholders": {} + }, + "logInTo": "Пријава на {homeserver}", + "@logInTo": { + "type": "text", + "placeholders": { + "homeserver": {} + } + }, + "logout": "Одјава", + "@logout": { + "type": "text", + "placeholders": {} + }, + "memberChanges": "Измене чланова", + "@memberChanges": { + "type": "text", + "placeholders": {} + }, + "mention": "Спомени", + "@mention": { + "type": "text", + "placeholders": {} + }, + "messages": "Поруке", + "@messages": { + "type": "text", + "placeholders": {} + }, + "moderator": "Модератор", + "@moderator": { + "type": "text", + "placeholders": {} + }, + "muteChat": "Ућуткај ћаскање", + "@muteChat": { + "type": "text", + "placeholders": {} + }, + "needPantalaimonWarning": "За сада, потребан је Пантелејмон (Pantalaimon) да бисте користили шифровање с краја на крај.", + "@needPantalaimonWarning": { + "type": "text", + "placeholders": {} + }, + "newChat": "Ново ћаскање", + "@newChat": { + "type": "text", + "placeholders": {} + }, + "newMessageInFluffyChat": "Нова порука — FluffyChat", + "@newMessageInFluffyChat": { + "type": "text", + "placeholders": {} + }, + "newVerificationRequest": "Нови захтев за верификацију!", + "@newVerificationRequest": { + "type": "text", + "placeholders": {} + }, + "next": "Следеће", + "@next": { + "type": "text", + "placeholders": {} + }, + "no": "Не", + "@no": { + "type": "text", + "placeholders": {} + }, + "noConnectionToTheServer": "Нема везе са сервером", + "@noConnectionToTheServer": { + "type": "text", + "placeholders": {} + }, + "noEmotesFound": "Нема емотија. 😕", + "@noEmotesFound": { + "type": "text", + "placeholders": {} + }, + "noEncryptionForPublicRooms": "Шифровање се може активирати након што соба престане да буде јавно доступна.", + "@noEncryptionForPublicRooms": { + "type": "text", + "placeholders": {} + }, + "noGoogleServicesWarning": "Чини се да немате Гугл услуге на телефону. То је добра одлука за вашу приватност! Да би се протурале нотификације у FluffyChat, препоручујемо коришћење https://microg.org/ или https://unifiedpush.org/", + "@noGoogleServicesWarning": { + "type": "text", + "placeholders": {} + }, + "none": "Ништа", + "@none": { + "type": "text", + "placeholders": {} + }, + "noPasswordRecoveryDescription": "Још нисте одредили начин за опоравак лозинке.", + "@noPasswordRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "noPermission": "Нема дозвола", + "@noPermission": { + "type": "text", + "placeholders": {} + }, + "noRoomsFound": "Нисам нашао собе…", + "@noRoomsFound": { + "type": "text", + "placeholders": {} + }, + "notifications": "Обавештења", + "@notifications": { + "type": "text", + "placeholders": {} + }, + "notificationsEnabledForThisAccount": "Обавештења укључена за овај налог", + "@notificationsEnabledForThisAccount": { + "type": "text", + "placeholders": {} + }, + "numUsersTyping": "{count} корисника куца…", + "@numUsersTyping": { + "type": "text", + "placeholders": { + "count": {} + } + }, + "offensive": "Увредљив", + "@offensive": { + "type": "text", + "placeholders": {} + }, + "offline": "Ван везе", + "@offline": { + "type": "text", + "placeholders": {} + }, + "ok": "у реду", + "@ok": { + "type": "text", + "placeholders": {} + }, + "online": "На вези", + "@online": { + "type": "text", + "placeholders": {} + }, + "onlineKeyBackupEnabled": "Резерва кључева на мрежи је укључена", + "@onlineKeyBackupEnabled": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "Нажалост, дошло је до грешке при подешавању дотурања обавештења.", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "oopsSomethingWentWrong": "Нешто је пошло наопако…", + "@oopsSomethingWentWrong": { + "type": "text", + "placeholders": {} + }, + "openAppToReadMessages": "Отворите апликацију да прочитате поруке", + "@openAppToReadMessages": { + "type": "text", + "placeholders": {} + }, + "openCamera": "Отвори камеру", + "@openCamera": { + "type": "text", + "placeholders": {} + }, + "or": "или", + "@or": { + "type": "text", + "placeholders": {} + }, + "participant": "Учесник", + "@participant": { + "type": "text", + "placeholders": {} + }, + "passphraseOrKey": "фраза или кључ опоравка", + "@passphraseOrKey": { + "type": "text", + "placeholders": {} + }, + "password": "Лозинка", + "@password": { + "type": "text", + "placeholders": {} + }, + "passwordForgotten": "Заборављена лозинка", + "@passwordForgotten": { + "type": "text", + "placeholders": {} + }, + "passwordHasBeenChanged": "Лозинка је промењена", + "@passwordHasBeenChanged": { + "type": "text", + "placeholders": {} + }, + "passwordRecovery": "Опоравак лозинке", + "@passwordRecovery": { + "type": "text", + "placeholders": {} + }, + "people": "Људи", + "@people": { + "type": "text", + "placeholders": {} + }, + "pickImage": "Избор слике", + "@pickImage": { + "type": "text", + "placeholders": {} + }, + "pin": "Закачи", + "@pin": { + "type": "text", + "placeholders": {} + }, + "play": "Пусти {fileName}", + "@play": { + "type": "text", + "placeholders": { + "fileName": {} + } + }, + "pleaseChoose": "Изаберите", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "pleaseChooseAPasscode": "Изаберите код за пролаз", + "@pleaseChooseAPasscode": { + "type": "text", + "placeholders": {} + }, + "pleaseClickOnLink": "Кликните на везу у примљеној е-пошти па наставите.", + "@pleaseClickOnLink": { + "type": "text", + "placeholders": {} + }, + "pleaseEnter4Digits": "Унесите 4 цифре или оставите празно да не закључавате апликацију.", + "@pleaseEnter4Digits": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPassword": "Унесите своју лозинку", + "@pleaseEnterYourPassword": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourPin": "Унесите свој пин", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "pleaseEnterYourUsername": "Унесите своје корисничко име", + "@pleaseEnterYourUsername": { + "type": "text", + "placeholders": {} + }, + "pleaseFollowInstructionsOnWeb": "Испратите упутства на веб сајту и тапните на „Следеће“.", + "@pleaseFollowInstructionsOnWeb": { + "type": "text", + "placeholders": {} + }, + "privacy": "Приватност", + "@privacy": { + "type": "text", + "placeholders": {} + }, + "publicRooms": "Јавне собе", + "@publicRooms": { + "type": "text", + "placeholders": {} + }, + "pushRules": "Правила протурања", + "@pushRules": { + "type": "text", + "placeholders": {} + }, + "reason": "Разлог", + "@reason": { + "type": "text", + "placeholders": {} + }, + "recording": "Снимам", + "@recording": { + "type": "text", + "placeholders": {} + }, + "redactedAnEvent": "{username} редигова догађај", + "@redactedAnEvent": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "redactMessage": "Редигуј поруку", + "@redactMessage": { + "type": "text", + "placeholders": {} + }, + "register": "Регистрација", + "@register": { + "type": "text", + "placeholders": {} + }, + "reject": "Одбиј", + "@reject": { + "type": "text", + "placeholders": {} + }, + "rejectedTheInvitation": "{username} одби позивницу", + "@rejectedTheInvitation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "rejoin": "Поново се придружи", + "@rejoin": { + "type": "text", + "placeholders": {} + }, + "remove": "Уклони", + "@remove": { + "type": "text", + "placeholders": {} + }, + "removeAllOtherDevices": "Уклони све остале уређаје", + "@removeAllOtherDevices": { + "type": "text", + "placeholders": {} + }, + "removedBy": "Уклонио корисник {username}", + "@removedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "removeDevice": "Уклони уређај", + "@removeDevice": { + "type": "text", + "placeholders": {} + }, + "unbanFromChat": "Уклони изгнанство", + "@unbanFromChat": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "Уклоните свој аватар", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "renderRichContent": "Приказуј обогаћен садржај поруке", + "@renderRichContent": { + "type": "text", + "placeholders": {} + }, + "replaceRoomWithNewerVersion": "Замени собу новијом верзијом", + "@replaceRoomWithNewerVersion": { + "type": "text", + "placeholders": {} + }, + "reply": "Одговори", + "@reply": { + "type": "text", + "placeholders": {} + }, + "reportMessage": "Пријави поруку", + "@reportMessage": { + "type": "text", + "placeholders": {} + }, + "requestPermission": "Затражи дозволу", + "@requestPermission": { + "type": "text", + "placeholders": {} + }, + "roomHasBeenUpgraded": "Соба је надограђена", + "@roomHasBeenUpgraded": { + "type": "text", + "placeholders": {} + }, + "roomVersion": "Верзија собе", + "@roomVersion": { + "type": "text", + "placeholders": {} + }, + "search": "Претражи", + "@search": { + "type": "text", + "placeholders": {} + }, + "security": "Безбедност", + "@security": { + "type": "text", + "placeholders": {} + }, + "seenByUser": "{username} прегледа", + "@seenByUser": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "send": "Пошаљи", + "@send": { + "type": "text", + "placeholders": {} + }, + "sendAMessage": "Пошаљи поруку", + "@sendAMessage": { + "type": "text", + "placeholders": {} + }, + "sendAudio": "Пошаљи аудио", + "@sendAudio": { + "type": "text", + "placeholders": {} + }, + "sendFile": "Пошаљи фајл", + "@sendFile": { + "type": "text", + "placeholders": {} + }, + "sendImage": "Пошаљи слику", + "@sendImage": { + "type": "text", + "placeholders": {} + }, + "sendMessages": "Слање порука", + "@sendMessages": { + "type": "text", + "placeholders": {} + }, + "sendOriginal": "Пошаљи оригинал", + "@sendOriginal": { + "type": "text", + "placeholders": {} + }, + "sendVideo": "Пошаљи видео", + "@sendVideo": { + "type": "text", + "placeholders": {} + }, + "sentAFile": "{username} посла фајл", + "@sentAFile": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAnAudio": "{username} посла аудио", + "@sentAnAudio": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAPicture": "{username} посла слику", + "@sentAPicture": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentASticker": "{username} посла налепницу", + "@sentASticker": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentAVideo": "{username} посла видео", + "@sentAVideo": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "sentCallInformations": "{senderName} посла податке о позиву", + "@sentCallInformations": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "setAsCanonicalAlias": "Постави као главни алијас", + "@setAsCanonicalAlias": { + "type": "text", + "placeholders": {} + }, + "setCustomEmotes": "постави посебне емотије", + "@setCustomEmotes": { + "type": "text", + "placeholders": {} + }, + "setInvitationLink": "Поставља везу позивнице", + "@setInvitationLink": { + "type": "text", + "placeholders": {} + }, + "setPermissionsLevel": "Одреди ниво дозволе", + "@setPermissionsLevel": { + "type": "text", + "placeholders": {} + }, + "setStatus": "Постави статус", + "@setStatus": { + "type": "text", + "placeholders": {} + }, + "settings": "Поставке", + "@settings": { + "type": "text", + "placeholders": {} + }, + "share": "Подели", + "@share": { + "type": "text", + "placeholders": {} + }, + "sharedTheLocation": "{username} подели локацију", + "@sharedTheLocation": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "showPassword": "Прикажи лозинку", + "@showPassword": { + "type": "text", + "placeholders": {} + }, + "singlesignon": "Јединствена пријава", + "@singlesignon": { + "type": "text", + "placeholders": {} + }, + "skip": "Прескочи", + "@skip": { + "type": "text", + "placeholders": {} + }, + "sourceCode": "Изворни код", + "@sourceCode": { + "type": "text", + "placeholders": {} + }, + "startedACall": "{senderName} започе позив", + "@startedACall": { + "type": "text", + "placeholders": { + "senderName": {} + } + }, + "status": "Стање", + "@status": { + "type": "text", + "placeholders": {} + }, + "statusExampleMessage": "Како сте данас?", + "@statusExampleMessage": { + "type": "text", + "placeholders": {} + }, + "submit": "Пошаљи", + "@submit": { + "type": "text", + "placeholders": {} + }, + "systemTheme": "системски", + "@systemTheme": { + "type": "text", + "placeholders": {} + }, + "theyDontMatch": "Не поклапају се", + "@theyDontMatch": { + "type": "text", + "placeholders": {} + }, + "theyMatch": "Поклапају се", + "@theyMatch": { + "type": "text", + "placeholders": {} + }, + "title": "FluffyChat", + "@title": { + "description": "Title for the application", + "type": "text", + "placeholders": {} + }, + "toggleFavorite": "Мењај омиљеност", + "@toggleFavorite": { + "type": "text", + "placeholders": {} + }, + "toggleMuted": "Мењај ућутканост", + "@toggleMuted": { + "type": "text", + "placeholders": {} + }, + "toggleUnread": "Означи не/прочитано", + "@toggleUnread": { + "type": "text", + "placeholders": {} + }, + "tooManyRequestsWarning": "Превише упита. Покушајте касније!", + "@tooManyRequestsWarning": { + "type": "text", + "placeholders": {} + }, + "transferFromAnotherDevice": "Пренос са другог уређаја", + "@transferFromAnotherDevice": { + "type": "text", + "placeholders": {} + }, + "tryToSendAgain": "Покушај слање поново", + "@tryToSendAgain": { + "type": "text", + "placeholders": {} + }, + "unavailable": "Недоступно", + "@unavailable": { + "type": "text", + "placeholders": {} + }, + "unbannedUser": "{username} одблокира корисника {targetName}", + "@unbannedUser": { + "type": "text", + "placeholders": { + "username": {}, + "targetName": {} + } + }, + "unblockDevice": "Одблокирај уређај", + "@unblockDevice": { + "type": "text", + "placeholders": {} + }, + "unknownDevice": "Непознат уређај", + "@unknownDevice": { + "type": "text", + "placeholders": {} + }, + "unknownEncryptionAlgorithm": "Непознат алгоритам шифровања", + "@unknownEncryptionAlgorithm": { + "type": "text", + "placeholders": {} + }, + "unknownEvent": "Непознат догађај „{type}“", + "@unknownEvent": { + "type": "text", + "placeholders": { + "type": {} + } + }, + "unmuteChat": "Врати обавештења", + "@unmuteChat": { + "type": "text", + "placeholders": {} + }, + "unpin": "Откачи", + "@unpin": { + "type": "text", + "placeholders": {} + }, + "unreadChats": "{unreadCount, plural, other{непрочитаних ћаскања: {unreadCount}}}", + "@unreadChats": { + "type": "text", + "placeholders": { + "unreadCount": {} + } + }, + "userAndOthersAreTyping": "{username} и {count} корисника куцају…", + "@userAndOthersAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "count": {} + } + }, + "userAndUserAreTyping": "{username} и {username2} куцају…", + "@userAndUserAreTyping": { + "type": "text", + "placeholders": { + "username": {}, + "username2": {} + } + }, + "userIsTyping": "{username} куца…", + "@userIsTyping": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "userLeftTheChat": "{username} напусти ћаскање", + "@userLeftTheChat": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "username": "Корисничко име", + "@username": { + "type": "text", + "placeholders": {} + }, + "userSentUnknownEvent": "{username} посла {type} догађај", + "@userSentUnknownEvent": { + "type": "text", + "placeholders": { + "username": {}, + "type": {} + } + }, + "verified": "Оверен", + "@verified": { + "type": "text", + "placeholders": {} + }, + "verify": "Верификуј", + "@verify": { + "type": "text", + "placeholders": {} + }, + "verifyStart": "Покрени верификацију", + "@verifyStart": { + "type": "text", + "placeholders": {} + }, + "verifySuccess": "Успешно сте верификовали!", + "@verifySuccess": { + "type": "text", + "placeholders": {} + }, + "verifyTitle": "Верификујем други налог", + "@verifyTitle": { + "type": "text", + "placeholders": {} + }, + "videoCall": "Видео позив", + "@videoCall": { + "type": "text", + "placeholders": {} + }, + "visibilityOfTheChatHistory": "Одреди видљивост историје", + "@visibilityOfTheChatHistory": { + "type": "text", + "placeholders": {} + }, + "visibleForAllParticipants": "видљиво свим учесницима", + "@visibleForAllParticipants": { + "type": "text", + "placeholders": {} + }, + "visibleForEveryone": "видљиво свима", + "@visibleForEveryone": { + "type": "text", + "placeholders": {} + }, + "voiceMessage": "Гласовна порука", + "@voiceMessage": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerAcceptRequest": "Чекам да саговорник прихвати захтев…", + "@waitingPartnerAcceptRequest": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerEmoji": "Чекам да саговорник прихвати емоџије…", + "@waitingPartnerEmoji": { + "type": "text", + "placeholders": {} + }, + "waitingPartnerNumbers": "Чекам да саговорник прихвати бројеве…", + "@waitingPartnerNumbers": { + "type": "text", + "placeholders": {} + }, + "wallpaper": "Тапета", + "@wallpaper": { + "type": "text", + "placeholders": {} + }, + "warning": "Упозорење!", + "@warning": { + "type": "text", + "placeholders": {} + }, + "weSentYouAnEmail": "Послали смо вам е-пошту", + "@weSentYouAnEmail": { + "type": "text", + "placeholders": {} + }, + "whoCanPerformWhichAction": "ко може шта да ради", + "@whoCanPerformWhichAction": { + "type": "text", + "placeholders": {} + }, + "whoIsAllowedToJoinThisGroup": "Ко може да се придружи групи", + "@whoIsAllowedToJoinThisGroup": { + "type": "text", + "placeholders": {} + }, + "whyDoYouWantToReportThis": "Зашто желите ово да пријавите?", + "@whyDoYouWantToReportThis": { + "type": "text", + "placeholders": {} + }, + "wipeChatBackup": "Да обришем резервну копију како би направио нови сигурносни кључ?", + "@wipeChatBackup": { + "type": "text", + "placeholders": {} + }, + "withTheseAddressesRecoveryDescription": "Са овим адресама можете опоравити своју лозинку.", + "@withTheseAddressesRecoveryDescription": { + "type": "text", + "placeholders": {} + }, + "writeAMessage": "напишите поруку…", + "@writeAMessage": { + "type": "text", + "placeholders": {} + }, + "yes": "Да", + "@yes": { + "type": "text", + "placeholders": {} + }, + "you": "Ви", + "@you": { + "type": "text", + "placeholders": {} + }, + "youAreNoLongerParticipatingInThisChat": "Више не учествујете у овом ћаскању", + "@youAreNoLongerParticipatingInThisChat": { + "type": "text", + "placeholders": {} + }, + "youHaveBeenBannedFromThisChat": "Забрањено вам је ово ћаскање", + "@youHaveBeenBannedFromThisChat": { + "type": "text", + "placeholders": {} + }, + "yourPublicKey": "Ваш јавни кључ", + "@yourPublicKey": { + "type": "text", + "placeholders": {} + } +} diff --git a/assets/l10n/intl_tr.arb b/assets/l10n/intl_tr.arb index aead65362..04e74ed26 100644 --- a/assets/l10n/intl_tr.arb +++ b/assets/l10n/intl_tr.arb @@ -563,7 +563,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "Öntanımlı izin seviyesi", + "defaultPermissionLevel": "Yeni kullanıcılar içi öntanımlı izin seviyesi", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -2706,5 +2706,102 @@ "knockRestricted": "Tıklatma kısıtlı", "@knockRestricted": {}, "restricted": "Kısıtlı", - "@restricted": {} + "@restricted": {}, + "swipeRightToLeftToReply": "Yanıtlamak için sağdan sola kaydır", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "false", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "countChatsAndCountParticipants": "{chats} sohbet ve {participants} katılımcı", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "noMoreChatsFound": "Başka sohbet bulunamadı...", + "@noMoreChatsFound": {}, + "goToSpace": "Alana git: {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "joinedChats": "Katılınan sohbetler", + "@joinedChats": {}, + "unread": "Okunmadı", + "@unread": {}, + "markAsUnread": "Okunmadı olarak işaretle", + "@markAsUnread": {}, + "space": "Alan", + "@space": {}, + "spaces": "Alanlar", + "@spaces": {}, + "inviteOtherUsers": "Diğer kullanıcıları bu sohbete davet et", + "@inviteOtherUsers": {}, + "changeTheChatPermissions": "Sohbet izinlerini değiştir", + "@changeTheChatPermissions": {}, + "changeTheCanonicalRoomAlias": "Ana herkese açık sohbet adresini değiştir", + "@changeTheCanonicalRoomAlias": {}, + "sendRoomNotifications": "@oda bildirimleri gönder", + "@sendRoomNotifications": {}, + "changeTheDescriptionOfTheGroup": "Sohbetin açıklamasını değiştir", + "@changeTheDescriptionOfTheGroup": {}, + "userLevel": "{level} - Kullanıcı", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - Moderatör", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - Yönetici", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeGeneralChatSettings": "Genel sohbet ayarlarını değiştir", + "@changeGeneralChatSettings": {}, + "changeTheVisibilityOfChatHistory": "Sohbet geçmişinin görünürlüğünü değiştir", + "@changeTheVisibilityOfChatHistory": {}, + "invitedBy": "📩 {user} davet etti", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "chatPermissionsDescription": "Bu sohbette belirli eylemler için hangi güç düzeyinin gerekli olduğunu tanımlayın. 0, 50 ve 100 güç düzeyleri genellikle kullanıcıları, moderatörleri ve yöneticileri temsil eder, ancak herhangi bir derecelendirme mümkündür.", + "@chatPermissionsDescription": {}, + "changelog": "Değişiklik günlüğü", + "@changelog": {}, + "updateInstalled": "🎉 Güncelleme {version} kuruldu!", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "sendCanceled": "Gönderme iptal edildi", + "@sendCanceled": {}, + "noChatsFoundHere": "Burada henüz sohbet bulunamadı. Aşağıdaki düğmeyi kullanarak biriyle yeni bir sohbet başlatın. ⤵️", + "@noChatsFoundHere": {}, + "loginWithMatrixId": "Matrix kimliği ile oturum aç", + "@loginWithMatrixId": {}, + "discoverHomeservers": "Ana sunucuları keşfet", + "@discoverHomeservers": {}, + "whatIsAHomeserver": "Ana sunucu nedir?", + "@whatIsAHomeserver": {}, + "homeserverDescription": "Tüm verileriniz tıpkı bir e-posta sağlayıcısı gibi ana sunucuda saklanır. Hangi ana sunucuyu kullanmak istediğinizi seçebilir ve herkesle iletişim kurmaya devam edebilirsiniz. https://matrix.org adresinden daha fazla bilgi edinin.", + "@homeserverDescription": {}, + "doesNotSeemToBeAValidHomeserver": "Uyumlu bir ana sunucu gibi görünmüyor. Yanlış URL mi?", + "@doesNotSeemToBeAValidHomeserver": {} } diff --git a/assets/l10n/intl_uk.arb b/assets/l10n/intl_uk.arb index 62c59b73e..519ce5cde 100644 --- a/assets/l10n/intl_uk.arb +++ b/assets/l10n/intl_uk.arb @@ -1557,7 +1557,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "Типовий рівень дозволів", + "defaultPermissionLevel": "Типовий рівень дозволів для нових користувачів", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -1913,12 +1913,12 @@ }, "unverified": "Неперевірений", "@unverified": {}, - "locationDisabledNotice": "Служби визначення місцеположення вимкнені. Увімкніть їх, щоб могти надавати доступ до вашого місцеположення.", + "locationDisabledNotice": "Служби визначення розташування вимкнені. Увімкніть їх, щоб мати змогу ділитися своїм розташуванням.", "@locationDisabledNotice": { "type": "text", "placeholders": {} }, - "locationPermissionDeniedNotice": "Дозвіл на розташування відхилено. Надайте можливість ділитися своїм місцеперебуванням.", + "locationPermissionDeniedNotice": "Дозвіл на розташування відхилено. Надайте можливість ділитися своїм розташуванням.", "@locationPermissionDeniedNotice": { "type": "text", "placeholders": {} @@ -2405,7 +2405,7 @@ "@makeAdminDescription": {}, "archiveRoomDescription": "Бесіду буде переміщено до архіву. Інші користувачі зможуть побачити, що ви вийшли з неї.", "@archiveRoomDescription": {}, - "hasKnocked": "{user} стукає до вас", + "hasKnocked": "🚪{user} стукає до вас", "@hasKnocked": { "placeholders": { "user": {} @@ -2436,7 +2436,7 @@ "query": {} } }, - "block": "блокування", + "block": "Заблокувати", "@block": {}, "yourGlobalUserIdIs": "Ваш глобальний ID користувача: ", "@yourGlobalUserIdIs": {}, @@ -2604,5 +2604,204 @@ "discover": "Огляд", "@discover": {}, "stickers": "Наліпки", - "@stickers": {} + "@stickers": {}, + "searchIn": "Пошук у бесіді \"{chat}\"...", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "commandHint_ignore": "Ігнорувати цей Matrix ID", + "@commandHint_ignore": {}, + "restricted": "Обмежено", + "@restricted": {}, + "swipeRightToLeftToReply": "Посунути праворуч або ліворуч, щоб відповісти", + "@swipeRightToLeftToReply": {}, + "globalChatId": "Глобальний ID бесіди", + "@globalChatId": {}, + "accessAndVisibility": "Доступ і видимість", + "@accessAndVisibility": {}, + "accessAndVisibilityDescription": "Хто може приєднатися до цієї бесіди і як її можна знайти.", + "@accessAndVisibilityDescription": {}, + "calls": "Виклики", + "@calls": {}, + "customEmojisAndStickers": "Власні емоджі та наліпки", + "@customEmojisAndStickers": {}, + "customEmojisAndStickersBody": "Додавайте або діліться власними емоджі або наліпками, які можна використовувати в будь-якій бесіді.", + "@customEmojisAndStickersBody": {}, + "createNewAddress": "Створити нову адресу", + "@createNewAddress": {}, + "userRole": "Роль користувача", + "@userRole": {}, + "minimumPowerLevel": "{level} — це найнижчий рівень повноважень.", + "@minimumPowerLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "commandHint_unignore": "Не ігнорувати цей Matrix ID", + "@commandHint_unignore": {}, + "knockRestricted": "Стук обмежено", + "@knockRestricted": {}, + "appLockDescription": "Блокувати застосунок, коли не використовується ПІН-код", + "@appLockDescription": {}, + "hideRedactedMessages": "Сховати змінені повідомлення", + "@hideRedactedMessages": {}, + "hideRedactedMessagesBody": "Якщо хтось змінить повідомлення, його більше не буде видно в бесіді.", + "@hideRedactedMessagesBody": {}, + "hideInvalidOrUnknownMessageFormats": "Сховати недійсні або невідомі формати повідомлень", + "@hideInvalidOrUnknownMessageFormats": {}, + "hideMemberChangesInPublicChats": "Сховати зміни користувачів у загальнодоступних бесідах", + "@hideMemberChangesInPublicChats": {}, + "hideMemberChangesInPublicChatsBody": "Не показувати в хронології бесіди, якщо хтось приєднується до загальнодоступної бесіди або виходить з неї, щоб покращити її читабельність.", + "@hideMemberChangesInPublicChatsBody": {}, + "overview": "Огляд", + "@overview": {}, + "notifyMeFor": "Сповіщати мене про", + "@notifyMeFor": {}, + "passwordRecoverySettings": "Налаштування відновлення пароля", + "@passwordRecoverySettings": {}, + "userWouldLikeToChangeTheChat": "{user} хоче приєднатися до бесіди.", + "@userWouldLikeToChangeTheChat": { + "placeholders": { + "user": {} + } + }, + "noPublicLinkHasBeenCreatedYet": "Загальнодоступне посилання ще не створено", + "@noPublicLinkHasBeenCreatedYet": {}, + "knock": "Постукатись", + "@knock": {}, + "knocking": "Стукаються", + "@knocking": {}, + "noDatabaseEncryption": "Шифрування бази даних не підтримується на цій платформі", + "@noDatabaseEncryption": {}, + "usersMustKnock": "Користувачі повинні постукатись", + "@usersMustKnock": {}, + "noOneCanJoin": "Ніхто не може приєднатись", + "@noOneCanJoin": {}, + "chatCanBeDiscoveredViaSearchOnServer": "Бесіду можна знайти за допомогою пошуку на {server}", + "@chatCanBeDiscoveredViaSearchOnServer": { + "type": "text", + "placeholders": { + "server": {} + } + }, + "publicChatAddresses": "Адреси загальнодоступної бесіди", + "@publicChatAddresses": {}, + "searchMore": "Шукати ще...", + "@searchMore": {}, + "gallery": "Галерея", + "@gallery": {}, + "files": "Файли", + "@files": {}, + "unreadChatsInApp": "{appname}: {unread} непрочитаних бесід", + "@unreadChatsInApp": { + "type": "text", + "placeholders": { + "appname": {}, + "unread": {} + } + }, + "thereAreCountUsersBlocked": "Наразі заблоковано {count} користувачів.", + "@thereAreCountUsersBlocked": { + "type": "text", + "count": {} + }, + "moderatorLevel": "{level} - Модератор", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - Адміністратор", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "userLevel": "{level} - Користувач", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "changeGeneralChatSettings": "Змінити загальні налаштування чату", + "@changeGeneralChatSettings": {}, + "inviteOtherUsers": "Запросити інших користувачів до цього чату", + "@inviteOtherUsers": {}, + "changeTheChatPermissions": "Змінити права доступу до чату", + "@changeTheChatPermissions": {}, + "changeTheVisibilityOfChatHistory": "Змінити видимість історії чату", + "@changeTheVisibilityOfChatHistory": {}, + "changeTheCanonicalRoomAlias": "Змінити основну адресу загальнодоступного чату", + "@changeTheCanonicalRoomAlias": {}, + "sendRoomNotifications": "Надсилати сповіщення @room", + "@sendRoomNotifications": {}, + "space": "Простір", + "@space": {}, + "spaces": "Простори", + "@spaces": {}, + "goToSpace": "Перейти до простору: {space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "Позначити непрочитаним", + "@markAsUnread": {}, + "alwaysUse24HourFormat": "ні", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "invitedBy": "📩 Запрошений {user}", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "changeTheDescriptionOfTheGroup": "Змінити опис чату", + "@changeTheDescriptionOfTheGroup": {}, + "updateInstalled": "🎉 Оновлення {version} встановлено!", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "changelog": "Зміни", + "@changelog": {}, + "chatPermissionsDescription": "Визначте, який рівень повноважень необхідний для певних дій у цьому чаті. Рівні повноважень 0, 50 і 100 зазвичай представляють користувачів, модераторів та адміністраторів, але можливі будь-які градації.", + "@chatPermissionsDescription": {}, + "countChatsAndCountParticipants": "{chats} чати та {participants} учасників", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "noMoreChatsFound": "Більше чатів не знайдено...", + "@noMoreChatsFound": {}, + "joinedChats": "Приєднані чати", + "@joinedChats": {}, + "unread": "Непрочитані", + "@unread": {}, + "sendCanceled": "Надсилання скасовано", + "@sendCanceled": {}, + "noChatsFoundHere": "Бесід ще немає. Розпочніть спілкування натиснувши кнопку нижче. ⤵️", + "@noChatsFoundHere": {}, + "loginWithMatrixId": "Увійти за допомогою Matrix-ID", + "@loginWithMatrixId": {}, + "discoverHomeservers": "Знайти домашні сервери", + "@discoverHomeservers": {}, + "whatIsAHomeserver": "Що таке домашній сервер?", + "@whatIsAHomeserver": {}, + "homeserverDescription": "Усі ваші дані зберігаються на домашньому сервері, так само як у постачальника послуг електронної пошти. Ви можете вибрати, який домашній сервер ви хочете використовувати, водночас ви можете спілкуватися з усіма. Докладніше на https://matrix.org.", + "@homeserverDescription": {}, + "doesNotSeemToBeAValidHomeserver": "Здається, це несумісний домашній сервер. Неправильна URL-адреса?", + "@doesNotSeemToBeAValidHomeserver": {} } diff --git a/assets/l10n/intl_zh.arb b/assets/l10n/intl_zh.arb index 72961c998..e73944e6a 100644 --- a/assets/l10n/intl_zh.arb +++ b/assets/l10n/intl_zh.arb @@ -537,7 +537,7 @@ "type": "text", "placeholders": {} }, - "defaultPermissionLevel": "默认权限级别", + "defaultPermissionLevel": "新用户默认权限级别", "@defaultPermissionLevel": { "type": "text", "placeholders": {} @@ -2706,5 +2706,102 @@ "knockRestricted": "“请求加入”请求受限", "@knockRestricted": {}, "restricted": "受限", - "@restricted": {} + "@restricted": {}, + "swipeRightToLeftToReply": "从右向左滑动进行回复", + "@swipeRightToLeftToReply": {}, + "alwaysUse24HourFormat": "false", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "noMoreChatsFound": "找不到更多聊天…", + "@noMoreChatsFound": {}, + "joinedChats": "已加入的聊天", + "@joinedChats": {}, + "space": "空间", + "@space": {}, + "spaces": "空间", + "@spaces": {}, + "goToSpace": "转到空间:{space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "标为未读", + "@markAsUnread": {}, + "countChatsAndCountParticipants": "{chats} 个聊天和 {participants} 名参与者", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "unread": "未读", + "@unread": {}, + "userLevel": "{level} - 用户", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - 主持人", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "adminLevel": "{level} - 管理员", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "inviteOtherUsers": "邀请其他用户到这个聊天", + "@inviteOtherUsers": {}, + "changeTheChatPermissions": "更改聊天权限", + "@changeTheChatPermissions": {}, + "changeTheVisibilityOfChatHistory": "更改聊天历史的可见性", + "@changeTheVisibilityOfChatHistory": {}, + "changeTheCanonicalRoomAlias": "更改主公共聊天地址", + "@changeTheCanonicalRoomAlias": {}, + "sendRoomNotifications": "发送通知聊天室所有人的通知", + "@sendRoomNotifications": {}, + "changeTheDescriptionOfTheGroup": "更改聊天描述", + "@changeTheDescriptionOfTheGroup": {}, + "changeGeneralChatSettings": "更改常规聊天设置", + "@changeGeneralChatSettings": {}, + "invitedBy": "📩 邀请人 {user}", + "@invitedBy": { + "placeholders": { + "user": {} + } + }, + "chatPermissionsDescription": "定义此聊天中哪个权限等级对特定操作是必需的。权限等级 0、50 和 100 通常代表用户、主持人和管理员,但你可以自定义任何等级。", + "@chatPermissionsDescription": {}, + "changelog": "更新记录", + "@changelog": {}, + "updateInstalled": "🎉 已安装更新 {version} !", + "@updateInstalled": { + "type": "text", + "placeholders": { + "version": {} + } + }, + "sendCanceled": "发送被取消", + "@sendCanceled": {}, + "noChatsFoundHere": "此处尚未找到聊天。使用下方按钮 ⤵️ 开始和某人的新聊天", + "@noChatsFoundHere": {}, + "loginWithMatrixId": "使用 Matrix-ID 登录", + "@loginWithMatrixId": {}, + "discoverHomeservers": "发现主服务器", + "@discoverHomeservers": {}, + "whatIsAHomeserver": "什么是主服务器?", + "@whatIsAHomeserver": {}, + "homeserverDescription": "主服务器上就像电子邮件提供商,你的所有数据都存储在上面。你可以选择你想使用哪个主服务器。在 https://matrix.org 上了解更多信息。", + "@homeserverDescription": {}, + "doesNotSeemToBeAValidHomeserver": "似乎不是兼容的主服务器。URL 不正确?", + "@doesNotSeemToBeAValidHomeserver": {} } diff --git a/assets/l10n/intl_zh_Hant.arb b/assets/l10n/intl_zh_Hant.arb index 8758122cf..9570c7214 100644 --- a/assets/l10n/intl_zh_Hant.arb +++ b/assets/l10n/intl_zh_Hant.arb @@ -5,12 +5,12 @@ "type": "text", "placeholders": {} }, - "accept": "接受", + "accept": "同意", "@accept": { "type": "text", "placeholders": {} }, - "acceptedTheInvitation": "👍{username}已接受邀請", + "acceptedTheInvitation": "👍 {username} 已接受邀請", "@acceptedTheInvitation": { "type": "text", "placeholders": { @@ -22,7 +22,7 @@ "type": "text", "placeholders": {} }, - "activatedEndToEndEncryption": "🔐{username}已啟用點對點加密", + "activatedEndToEndEncryption": "🔐 {username} 已啟用點對點加密", "@activatedEndToEndEncryption": { "type": "text", "placeholders": { @@ -49,7 +49,7 @@ "type": "text", "placeholders": {} }, - "answeredTheCall": "已開始與{senderName}通話", + "answeredTheCall": "已開始與 {senderName} 通話", "@answeredTheCall": { "type": "text", "placeholders": { @@ -91,7 +91,7 @@ "type": "text", "placeholders": {} }, - "askVerificationRequest": "是否接受來自{username}的驗證申請?", + "askVerificationRequest": "是否接受來自 {username} 的驗證申請?", "@askVerificationRequest": { "type": "text", "placeholders": { @@ -106,7 +106,7 @@ "supportedVersions": {} } }, - "badServerVersionsException": "目前伺服器支援的Spec版本:\n{serverVersions}\n但本應用程式僅支援{supportedVersions}", + "badServerVersionsException": "目前伺服器支援的協議版本:\n{serverVersions}\n但本應用程式僅支援 {supportedVersions}", "@badServerVersionsException": { "type": "text", "placeholders": { @@ -114,17 +114,17 @@ "supportedVersions": {} } }, - "banFromChat": "已從聊天室中封禁", + "banFromChat": "已從聊天室中封鎖", "@banFromChat": { "type": "text", "placeholders": {} }, - "banned": "已被封禁", + "banned": "已被封鎖", "@banned": { "type": "text", "placeholders": {} }, - "bannedUser": "{username}封禁了{targetName}", + "bannedUser": "{username} 封鎖了 {targetName}", "@bannedUser": { "type": "text", "placeholders": { @@ -157,14 +157,14 @@ "type": "text", "placeholders": {} }, - "changedTheChatAvatar": "{username}變更了對話頭貼", + "changedTheChatAvatar": "{username} 變更了對話頭貼", "@changedTheChatAvatar": { "type": "text", "placeholders": { "username": {} } }, - "changedTheChatDescriptionTo": "{username}變更了對話介紹為:「{description}」", + "changedTheChatDescriptionTo": "{username} 變更了聊天室介紹為:「{description}」", "@changedTheChatDescriptionTo": { "type": "text", "placeholders": { @@ -172,7 +172,7 @@ "description": {} } }, - "changedTheChatNameTo": "{username}變更了暱稱為:「{chatname}」", + "changedTheChatNameTo": "{username} 變更了聊天室名稱為:「{chatname}」", "@changedTheChatNameTo": { "type": "text", "placeholders": { @@ -180,7 +180,7 @@ "chatname": {} } }, - "changedTheChatPermissions": "{username}變更了對話權限", + "changedTheChatPermissions": "{username} 變更了對話權限", "@changedTheChatPermissions": { "type": "text", "placeholders": { @@ -195,14 +195,14 @@ "displayname": {} } }, - "changedTheGuestAccessRules": "{username}變更了訪客訪問規則", + "changedTheGuestAccessRules": "{username} 變更了訪客訪問規則", "@changedTheGuestAccessRules": { "type": "text", "placeholders": { "username": {} } }, - "changedTheGuestAccessRulesTo": "{username}變更了訪客訪問規則為:{rules}", + "changedTheGuestAccessRulesTo": "{username} 變更了訪客訪問規則為:{rules}", "@changedTheGuestAccessRulesTo": { "type": "text", "placeholders": { @@ -210,14 +210,14 @@ "rules": {} } }, - "changedTheHistoryVisibility": "{username}變更了歷史記錄觀察狀態", + "changedTheHistoryVisibility": "{username} 變更了歷史記錄觀察狀態", "@changedTheHistoryVisibility": { "type": "text", "placeholders": { "username": {} } }, - "changedTheHistoryVisibilityTo": "{username}變更了歷史紀錄觀察狀態到:{rules}", + "changedTheHistoryVisibilityTo": "{username} 變更了歷史紀錄觀察狀態到:{rules}", "@changedTheHistoryVisibilityTo": { "type": "text", "placeholders": { @@ -225,14 +225,14 @@ "rules": {} } }, - "changedTheJoinRules": "{username}變更了加入的規則", + "changedTheJoinRules": "{username} 變更了加入的規則", "@changedTheJoinRules": { "type": "text", "placeholders": { "username": {} } }, - "changedTheJoinRulesTo": "{username}變更了加入的規則為:{joinRules}", + "changedTheJoinRulesTo": "{username} 變更了加入的規則為:{joinRules}", "@changedTheJoinRulesTo": { "type": "text", "placeholders": { @@ -240,21 +240,21 @@ "joinRules": {} } }, - "changedTheProfileAvatar": "{username}變更了頭貼", + "changedTheProfileAvatar": "{username} 變更了頭貼", "@changedTheProfileAvatar": { "type": "text", "placeholders": { "username": {} } }, - "changedTheRoomAliases": "{username}變更了聊天室名", + "changedTheRoomAliases": "{username} 變更了聊天室名", "@changedTheRoomAliases": { "type": "text", "placeholders": { "username": {} } }, - "changedTheRoomInvitationLink": "{username}變更了邀請連結", + "changedTheRoomInvitationLink": "{username} 變更了邀請連結", "@changedTheRoomInvitationLink": { "type": "text", "placeholders": { @@ -286,7 +286,7 @@ "type": "text", "placeholders": {} }, - "chat": "聊天", + "chat": "聊天室", "@chat": { "type": "text", "placeholders": {} @@ -296,7 +296,7 @@ "type": "text", "placeholders": {} }, - "chatBackupDescription": "您的過往聊天記錄已被恢復金鑰加密。請您確保不會弄丟它。", + "chatBackupDescription": "您的過往聊天室記錄已被恢復金鑰加密。請您確保不會弄丟它。", "@chatBackupDescription": { "type": "text", "placeholders": {} @@ -316,12 +316,12 @@ "type": "text", "placeholders": {} }, - "compareEmojiMatch": "對比並確認這些表情符合其他那些裝置:", + "compareEmojiMatch": "請對比這些表情", "@compareEmojiMatch": { "type": "text", "placeholders": {} }, - "compareNumbersMatch": "比較以下數字,確保它們和另一個裝置上的相同:", + "compareNumbersMatch": "請對比這些數字", "@compareNumbersMatch": { "type": "text", "placeholders": {} @@ -383,7 +383,7 @@ "error": {} } }, - "countParticipants": "{count}個參與者", + "countParticipants": "{count} 個參與者", "@countParticipants": { "type": "text", "placeholders": { @@ -395,7 +395,7 @@ "type": "text", "placeholders": {} }, - "createdTheChat": "{username}建立了聊天室", + "createdTheChat": "💬 {username} 建立了聊天室", "@createdTheChat": { "type": "text", "placeholders": { @@ -412,7 +412,7 @@ "type": "text", "placeholders": {} }, - "dateAndTimeOfDay": "{date}, {timeOfDay}", + "dateAndTimeOfDay": "{date} , {timeOfDay}", "@dateAndTimeOfDay": { "type": "text", "placeholders": { @@ -420,7 +420,7 @@ "timeOfDay": {} } }, - "dateWithoutYear": "{month}-{day}", + "dateWithoutYear": "{month} - {day}", "@dateWithoutYear": { "type": "text", "placeholders": { @@ -428,7 +428,7 @@ "day": {} } }, - "dateWithYear": "{year}-{month}-{day}", + "dateWithYear": "{year} - {month} - {day}", "@dateWithYear": { "type": "text", "placeholders": { @@ -562,7 +562,7 @@ "type": "text", "placeholders": {} }, - "encrypted": "加密的", + "encrypted": "已加密的", "@encrypted": { "type": "text", "placeholders": {} @@ -577,7 +577,7 @@ "type": "text", "placeholders": {} }, - "endedTheCall": "{senderName}結束了通話", + "endedTheCall": "{senderName} 結束了通話", "@endedTheCall": { "type": "text", "placeholders": { @@ -649,7 +649,7 @@ "type": "text", "placeholders": {} }, - "groupWith": "名稱為{displayname}的群組", + "groupWith": "名稱為 {displayname} 的群組", "@groupWith": { "type": "text", "placeholders": { @@ -666,7 +666,7 @@ "type": "text", "placeholders": {} }, - "hasWithdrawnTheInvitationFor": "{username}收回了對{targetName}的邀請", + "hasWithdrawnTheInvitationFor": "{username} 收回了對 {targetName} 的邀請", "@hasWithdrawnTheInvitationFor": { "type": "text", "placeholders": { @@ -734,7 +734,7 @@ "type": "text", "placeholders": {} }, - "inviteContactToGroup": "邀請聯絡人到{groupName}", + "inviteContactToGroup": "邀請聯絡人到 {groupName}", "@inviteContactToGroup": { "type": "text", "placeholders": { @@ -746,7 +746,7 @@ "type": "text", "placeholders": {} }, - "invitedUser": "{username}邀請了{targetName}", + "invitedUser": "📩 {username} 邀請了 {targetName}", "@invitedUser": { "type": "text", "placeholders": { @@ -764,7 +764,7 @@ "type": "text", "placeholders": {} }, - "inviteText": "{username}邀請您使用FluffyChat\n1. 安裝FluffyChat:https://fluffychat.im\n2. 登入或註冊\n3. 打開該邀請網址:{link}", + "inviteText": "{username} 邀請您使用 FluffyChat\n1. 安裝 FluffyChat:https://fluffychat.im\n2. 登入或註冊\n3. 打開該邀請網址:\n{link}", "@inviteText": { "type": "text", "placeholders": { @@ -777,7 +777,7 @@ "type": "text", "placeholders": {} }, - "joinedTheChat": "{username}加入了聊天室", + "joinedTheChat": "👋 {username} 加入了聊天室", "@joinedTheChat": { "type": "text", "placeholders": { @@ -789,7 +789,7 @@ "type": "text", "placeholders": {} }, - "kicked": "{username}踢了{targetName}", + "kicked": "👞 {username} 踢了 {targetName}", "@kicked": { "type": "text", "placeholders": { @@ -797,7 +797,7 @@ "targetName": {} } }, - "kickedAndBanned": "{username}踢了{targetName}並將其封禁", + "kickedAndBanned": "🙅 {username} 踢了 {targetName} 並將其封鎖", "@kickedAndBanned": { "type": "text", "placeholders": { @@ -837,19 +837,19 @@ "type": "text", "placeholders": {} }, - "loadCountMoreParticipants": "載入{count}個更多的參與者", + "loadCountMoreParticipants": "載入 {count} 個更多的參與者", "@loadCountMoreParticipants": { "type": "text", "placeholders": { "count": {} } }, - "loadingPleaseWait": "載入中… 請稍候。", + "loadingPleaseWait": "載入中...... 請稍候。", "@loadingPleaseWait": { "type": "text", "placeholders": {} }, - "loadMore": "載入更多…", + "loadMore": "載入更多...…", "@loadMore": { "type": "text", "placeholders": {} @@ -859,7 +859,7 @@ "type": "text", "placeholders": {} }, - "logInTo": "登入{homeserver}", + "logInTo": "登入 {homeserver}", "@logInTo": { "type": "text", "placeholders": { @@ -896,17 +896,17 @@ "type": "text", "placeholders": {} }, - "needPantalaimonWarning": "請注意您需要Pantalaimon才能使用點對點加密功能。", + "needPantalaimonWarning": "請注意您需要 Pantalaimon 才能使用點對點加密功能。", "@needPantalaimonWarning": { "type": "text", "placeholders": {} }, - "newChat": "新聊天室", + "newChat": "新聊天", "@newChat": { "type": "text", "placeholders": {} }, - "newMessageInFluffyChat": "來自 FluffyChat 的新訊息", + "newMessageInFluffyChat": "💬 來自 FluffyChat 的新訊息", "@newMessageInFluffyChat": { "type": "text", "placeholders": {} @@ -941,7 +941,7 @@ "type": "text", "placeholders": {} }, - "noGoogleServicesWarning": "看起來您手機上沒有Google服務框架。這對於保護您的隱私而言是個好決定!但為了收到FluffyChat的推播通知,我們推薦您使用 https://microg.org/ 或 https://unifiedpush.org/。", + "noGoogleServicesWarning": "您手機上沒有安裝 Google 服務框架。這或許對於保護您的隱私而言是個好事!但為了收到 FluffyChat 的推播通知,我們建議您使用 https://microg.org 或 https://unifiedpush.org。", "@noGoogleServicesWarning": { "type": "text", "placeholders": {} @@ -961,7 +961,7 @@ "type": "text", "placeholders": {} }, - "noRoomsFound": "找不到聊天室…", + "noRoomsFound": "找不到聊天室...…", "@noRoomsFound": { "type": "text", "placeholders": {} @@ -976,7 +976,7 @@ "type": "text", "placeholders": {} }, - "numUsersTyping": "{count}個人正在輸入…", + "numUsersTyping": "{count} 個人正在輸入...…", "@numUsersTyping": { "type": "text", "placeholders": { @@ -1008,7 +1008,7 @@ "type": "text", "placeholders": {} }, - "oopsSomethingWentWrong": "哎呀!出了一點差錯…", + "oopsSomethingWentWrong": "哎呀!出了一點差錯...…", "@oopsSomethingWentWrong": { "type": "text", "placeholders": {} @@ -1063,7 +1063,7 @@ "type": "text", "placeholders": {} }, - "play": "播放{fileName}", + "play": "播放 {fileName}", "@play": { "type": "text", "placeholders": { @@ -1125,7 +1125,7 @@ "type": "text", "placeholders": {} }, - "redactedAnEvent": "{username}編輯了一個事件", + "redactedAnEvent": "{username} 編輯了一個事件", "@redactedAnEvent": { "type": "text", "placeholders": { @@ -1142,7 +1142,7 @@ "type": "text", "placeholders": {} }, - "rejectedTheInvitation": "{username}拒絕了邀請", + "rejectedTheInvitation": "{username} 拒絕了邀請", "@rejectedTheInvitation": { "type": "text", "placeholders": { @@ -1164,7 +1164,7 @@ "type": "text", "placeholders": {} }, - "removedBy": "被{username}移除", + "removedBy": "被 {username} 移除", "@removedBy": { "type": "text", "placeholders": { @@ -1176,7 +1176,7 @@ "type": "text", "placeholders": {} }, - "unbanFromChat": "解禁聊天", + "unbanFromChat": "解封聊天室", "@unbanFromChat": { "type": "text", "placeholders": {} @@ -1221,7 +1221,7 @@ "type": "text", "placeholders": {} }, - "seenByUser": "{username}已讀", + "seenByUser": "{username} 已讀", "@seenByUser": { "type": "text", "placeholders": { @@ -1268,21 +1268,21 @@ "type": "text", "placeholders": {} }, - "sentAFile": "{username}傳送了一個文件", + "sentAFile": "{username} 傳送了一個文件", "@sentAFile": { "type": "text", "placeholders": { "username": {} } }, - "sentAnAudio": "{username}傳送了一個音訊", + "sentAnAudio": "{username} 傳送了一個音訊", "@sentAnAudio": { "type": "text", "placeholders": { "username": {} } }, - "sentAPicture": "{username}傳送了一張圖片", + "sentAPicture": "{username} 傳送了一張圖片", "@sentAPicture": { "type": "text", "placeholders": { @@ -1320,7 +1320,7 @@ "type": "text", "placeholders": {} }, - "setPermissionsLevel": "設定權限級別", + "setPermissionsLevel": "設定權限等級", "@setPermissionsLevel": { "type": "text", "placeholders": {} @@ -1362,7 +1362,7 @@ "type": "text", "placeholders": {} }, - "startedACall": "{senderName}開始了通話", + "startedACall": "{senderName} 開始了通話", "@startedACall": { "type": "text", "placeholders": { @@ -1415,7 +1415,7 @@ "type": "text", "placeholders": {} }, - "toggleUnread": "標記為已讀/未讀", + "toggleUnread": "標示為已讀/未讀", "@toggleUnread": { "type": "text", "placeholders": {} @@ -1440,7 +1440,7 @@ "type": "text", "placeholders": {} }, - "unbannedUser": "{username}解除封禁了{targetName}", + "unbannedUser": "{username} 解除封鎖了 {targetName}", "@unbannedUser": { "type": "text", "placeholders": { @@ -1480,14 +1480,14 @@ "type": "text", "placeholders": {} }, - "unreadChats": "{unreadCount, plural, =1{1 unread chat} other{{unreadCount} 個未讀聊天室}}", + "unreadChats": "{unreadCount, plural, =1 {1 unread chat} other { {unreadCount} 個未讀聊天室} }", "@unreadChats": { "type": "text", "placeholders": { "unreadCount": {} } }, - "userAndOthersAreTyping": "{username}和其他{count}個人正在輸入…", + "userAndOthersAreTyping": "{username} 和其他 {count} 個人正在輸入...…", "@userAndOthersAreTyping": { "type": "text", "placeholders": { @@ -1495,7 +1495,7 @@ "count": {} } }, - "userAndUserAreTyping": "{username}和{username2}正在輸入…", + "userAndUserAreTyping": "{username} 和 {username2} 正在輸入...…", "@userAndUserAreTyping": { "type": "text", "placeholders": { @@ -1503,14 +1503,14 @@ "username2": {} } }, - "userIsTyping": "{username}正在輸入…", + "userIsTyping": "{username} 正在輸入...…", "@userIsTyping": { "type": "text", "placeholders": { "username": {} } }, - "userLeftTheChat": "{username}離開了聊天室", + "userLeftTheChat": "{username} 離開了聊天室", "@userLeftTheChat": { "type": "text", "placeholders": { @@ -1522,7 +1522,7 @@ "type": "text", "placeholders": {} }, - "userSentUnknownEvent": "{username}傳送了一個{type}事件", + "userSentUnknownEvent": "{username} 傳送了一個 {type} 事件", "@userSentUnknownEvent": { "type": "text", "placeholders": { @@ -1560,7 +1560,7 @@ "type": "text", "placeholders": {} }, - "visibilityOfTheChatHistory": "聊天記錄的可見性", + "visibilityOfTheChatHistory": "聊天室記錄的可見性", "@visibilityOfTheChatHistory": { "type": "text", "placeholders": {} @@ -1580,22 +1580,22 @@ "type": "text", "placeholders": {} }, - "waitingPartnerAcceptRequest": "正在等待夥伴接受請求…", + "waitingPartnerAcceptRequest": "正在等待夥伴接受請求...…", "@waitingPartnerAcceptRequest": { "type": "text", "placeholders": {} }, - "waitingPartnerEmoji": "正在等待夥伴接受表情符號…", + "waitingPartnerEmoji": "正在等待夥伴接受表情符號...…", "@waitingPartnerEmoji": { "type": "text", "placeholders": {} }, - "waitingPartnerNumbers": "正在等待夥伴接受數字…", + "waitingPartnerNumbers": "正在等待夥伴接受數字...…", "@waitingPartnerNumbers": { "type": "text", "placeholders": {} }, - "wallpaper": "桌布", + "wallpaper": "桌布:", "@wallpaper": { "type": "text", "placeholders": {} @@ -1625,7 +1625,7 @@ "type": "text", "placeholders": {} }, - "wipeChatBackup": "要清除您的聊天記錄備份以建立新的安全金鑰嗎?", + "wipeChatBackup": "是否清除您的聊天室記錄備份以建立新的安全金鑰嗎?", "@wipeChatBackup": { "type": "text", "placeholders": {} @@ -1635,7 +1635,7 @@ "type": "text", "placeholders": {} }, - "writeAMessage": "輸入訊息…", + "writeAMessage": "輸入訊息...…", "@writeAMessage": { "type": "text", "placeholders": {} @@ -1655,7 +1655,7 @@ "type": "text", "placeholders": {} }, - "youHaveBeenBannedFromThisChat": "您已經被這個聊天室封禁", + "youHaveBeenBannedFromThisChat": "您已經被這個聊天室封鎖", "@youHaveBeenBannedFromThisChat": { "type": "text", "placeholders": {} @@ -1680,7 +1680,7 @@ "type": "text", "placeholders": {} }, - "commandHint_ban": "在此聊天室封禁該使用者", + "commandHint_ban": "在此聊天室封鎖該使用者", "@commandHint_ban": { "type": "text", "description": "Usage hint for the command /ban" @@ -1690,7 +1690,7 @@ "type": "text", "description": "Usage hint for the command /clearcache" }, - "commandHint_create": "建立一個空的群聊\n使用 --no-encryption 選項來禁用加密", + "commandHint_create": "建立一個空的群聊\n使用 --no-encryption 選項來停用加密", "@commandHint_create": { "type": "text", "description": "Usage hint for the command /create" @@ -1700,7 +1700,7 @@ "type": "text", "description": "Usage hint for the command /discardsession" }, - "commandHint_dm": "啟動一對一聊天\n使用 --no-encryption 選項來禁用加密", + "commandHint_dm": "啟動一對一聊天室\n使用 --no-encryption 選項來停用加密", "@commandHint_dm": { "type": "text", "description": "Usage hint for the command /dm" @@ -1742,7 +1742,7 @@ }, "addToSpace": "加入空間", "@addToSpace": {}, - "cantOpenUri": "無法打開URI {uri}", + "cantOpenUri": "無法打開 URI {uri}", "@cantOpenUri": { "type": "text", "placeholders": { @@ -1751,19 +1751,19 @@ }, "repeatPassword": "再次輸入密碼", "@repeatPassword": {}, - "yourChatBackupHasBeenSetUp": "您的聊天記錄備份已設定。", + "yourChatBackupHasBeenSetUp": "您的聊天室記錄備份已設定。", "@yourChatBackupHasBeenSetUp": {}, "goToTheNewRoom": "前往新聊天室", "@goToTheNewRoom": { "type": "text", "placeholders": {} }, - "commandHint_myroomavatar": "設置您的聊天室頭貼(通過 mxc-uri)", + "commandHint_myroomavatar": "設定您的聊天室頭貼(通過 mxc-uri)", "@commandHint_myroomavatar": { "type": "text", "description": "Usage hint for the command /myroomavatar" }, - "commandHint_unban": "在此聊天室解封該使用者", + "commandHint_unban": "在此聊天室解除封鎖該使用者", "@commandHint_unban": { "type": "text", "description": "Usage hint for the command /unban" @@ -1773,276 +1773,46 @@ "type": "text", "placeholder": {} }, - "sendOnEnter": "按 Enter 鍵發送", + "sendOnEnter": "按 Enter 鍵傳送", "@sendOnEnter": {}, "changeYourAvatar": "更改您的大頭貼", "@changeYourAvatar": { "type": "text", "placeholders": {} }, - "chatHasBeenAddedToThisSpace": "聊天室已添加到此空間", + "chatHasBeenAddedToThisSpace": "聊天室已新增到此空間", "@chatHasBeenAddedToThisSpace": {}, "clearArchive": "清除存檔", "@clearArchive": {}, - "hugContent": "{senderName}擁抱您", + "hugContent": "{senderName} 擁抱您", "@hugContent": { "type": "text", "placeholders": { "senderName": {} } }, - "@jumpToLastReadMessage": {}, - "@allRooms": { - "type": "text", - "placeholders": {} - }, - "@obtainingLocation": { - "type": "text", - "placeholders": {} - }, - "commandHint_cuddle": "發送一個摟抱表情", + "commandHint_cuddle": "傳送一個摟抱表情", "@commandHint_cuddle": {}, - "@widgetVideo": {}, - "@dismiss": {}, - "@reportErrorDescription": {}, - "@addAccount": {}, - "@removeYourAvatar": { - "type": "text", - "placeholders": {} - }, - "@unsupportedAndroidVersion": {}, - "@commandHint_html": { - "type": "text", - "description": "Usage hint for the command /html" - }, - "@widgetJitsi": {}, - "@messageType": {}, - "@indexedDbErrorLong": {}, - "@oneClientLoggedOut": {}, - "@startFirstChat": {}, - "@callingAccount": {}, - "@setColorTheme": {}, - "@nextAccount": {}, - "@singlesignon": { - "type": "text", - "placeholders": {} - }, - "@allSpaces": {}, - "supposedMxid": "此處應爲{mxid}", + "supposedMxid": "此處應爲 {mxid}", "@supposedMxid": { "type": "text", "placeholders": { "mxid": {} } }, - "@user": {}, - "@youAcceptedTheInvitation": {}, - "@noMatrixServer": { - "type": "text", - "placeholders": { - "server1": {}, - "server2": {} - } - }, - "@youInvitedBy": { - "placeholders": { - "user": {} - } - }, - "@banUserDescription": {}, - "@widgetEtherpad": {}, - "@removeDevicesDescription": {}, - "@separateChatTypes": { - "type": "text", - "placeholders": {} - }, - "@tryAgain": {}, - "@youKickedAndBanned": { - "placeholders": { - "user": {} - } - }, - "@unbanUserDescription": {}, - "@saveFile": { - "type": "text", - "placeholders": {} - }, - "@youRejectedTheInvitation": {}, - "@otherCallingPermissions": {}, - "@messagesStyle": {}, - "@link": {}, - "@widgetUrlError": {}, - "@emailOrUsername": {}, - "@newSpaceDescription": {}, - "@chatDescription": {}, - "@callingAccountDetails": {}, - "@enterSpace": {}, - "@encryptThisChat": {}, - "@previousAccount": {}, - "@reopenChat": {}, - "@pleaseEnterRecoveryKey": {}, - "@widgetNameError": {}, - "@addToBundle": {}, - "@spaceIsPublic": { - "type": "text", - "placeholders": {} - }, - "@addWidget": {}, - "@countFiles": { - "placeholders": { - "count": {} - } - }, - "@noKeyForThisMessage": {}, - "@shareLocation": { - "type": "text", - "placeholders": {} - }, - "@commandHint_markasgroup": {}, - "@errorObtainingLocation": { - "type": "text", - "placeholders": { - "error": {} - } - }, - "@hydrateTor": {}, - "@pushNotificationsNotAvailable": {}, - "@storeInAppleKeyChain": {}, - "@hydrate": {}, "invalidServerName": "伺服器名稱錯誤", "@invalidServerName": {}, - "@chatPermissions": {}, - "@sender": {}, - "@storeInAndroidKeystore": {}, - "@signInWithPassword": {}, - "@makeAdminDescription": {}, - "@synchronizingPleaseWait": { - "type": "text", - "placeholders": {} - }, - "@saveKeyManuallyDescription": {}, - "@editBundlesForAccount": {}, - "@whyIsThisMessageEncrypted": {}, - "@setChatDescription": {}, - "@spaceName": { - "type": "text", - "placeholders": {} - }, - "importFromZipFile": "從 zip 檔案匯入", + "importFromZipFile": "從 .zip 檔案匯入", "@importFromZipFile": {}, - "@or": { - "type": "text", - "placeholders": {} - }, - "@dehydrateWarning": {}, - "@noOtherDevicesFound": {}, - "@redactedBy": { - "type": "text", - "placeholders": { - "username": {} - } - }, - "@videoCallsBetaWarning": {}, - "@signInWith": { - "type": "text", - "placeholders": { - "provider": {} - } - }, - "@fileIsTooBigForServer": {}, "homeserver": "伺服器", "@homeserver": {}, - "@callingPermissions": {}, - "@readUpToHere": {}, - "@start": {}, - "@register": { - "type": "text", - "placeholders": {} - }, - "@unlockOldMessages": {}, - "@numChats": { - "type": "number", - "placeholders": { - "number": {} - } - }, - "@optionalRedactReason": {}, - "@dehydrate": {}, - "@locationPermissionDeniedNotice": { - "type": "text", - "placeholders": {} - }, - "@sendAsText": { - "type": "text" - }, - "@archiveRoomDescription": {}, - "exportEmotePack": "將表情包匯出成 zip 檔案", + "exportEmotePack": "將表情包匯出成 .zip 檔案", "@exportEmotePack": {}, - "@sendSticker": { - "type": "text", - "placeholders": {} - }, - "@switchToAccount": { - "type": "number", - "placeholders": { - "number": {} - } - }, "commandInvalid": "命令無效", "@commandInvalid": { "type": "text" }, - "@setAsCanonicalAlias": { - "type": "text", - "placeholders": {} - }, - "@locationDisabledNotice": { - "type": "text", - "placeholders": {} - }, - "@commandHint_plain": { - "type": "text", - "description": "Usage hint for the command /plain" - }, - "@experimentalVideoCalls": {}, - "@pleaseEnterRecoveryKeyDescription": {}, - "@openInMaps": { - "type": "text", - "placeholders": {} - }, - "@inviteContactToGroupQuestion": {}, - "@redactedByBecause": { - "type": "text", - "placeholders": { - "username": {}, - "reason": {} - } - }, - "@youHaveWithdrawnTheInvitationFor": { - "placeholders": { - "user": {} - } - }, - "@appearOnTopDetails": {}, - "@enterRoom": {}, - "@reportUser": {}, - "@commandHint_send": { - "type": "text", - "description": "Usage hint for the command /send" - }, - "@confirmEventUnpin": {}, - "@youInvitedUser": { - "placeholders": { - "user": {} - } - }, - "@fileHasBeenSavedAt": { - "type": "text", - "placeholders": { - "path": {} - } - }, - "commandMissing": "{command}不是正確的命令。", + "commandMissing": "{command} 不是正確的命令。", "@commandMissing": { "type": "text", "placeholders": { @@ -2050,103 +1820,643 @@ }, "description": "State that {command} is not a valid /command." }, - "@redactMessageDescription": {}, - "@recoveryKey": {}, - "@invalidInput": {}, - "@dehydrateTorLong": {}, - "@doNotShowAgain": {}, - "@report": {}, - "@unverified": {}, - "@serverRequiresEmail": {}, - "@hideUnimportantStateEvents": {}, - "@screenSharingTitle": {}, - "@widgetCustom": {}, - "@addToSpaceDescription": {}, - "googlyEyesContent": "{senderName}向您發送了瞪眼表情", + "googlyEyesContent": "{senderName} 向您傳送了瞪眼表情", "@googlyEyesContent": { "type": "text", "placeholders": { "senderName": {} } }, - "@youBannedUser": { + "addChatDescription": "新增聊天室描述......", + "@addChatDescription": {}, + "sendTypingNotifications": "傳送「輸入中」通知", + "@sendTypingNotifications": {}, + "importEmojis": "匯入表情包", + "@importEmojis": {}, + "confirmMatrixId": "如需刪除你的帳戶,請確認你的 Matrix ID。", + "@confirmMatrixId": {}, + "notAnImage": "不是圖片檔案。", + "@notAnImage": {}, + "cuddleContent": "{senderName} 摟抱您", + "@cuddleContent": { + "type": "text", "placeholders": { - "user": {} + "senderName": {} } }, - "addChatDescription": "新增聊天說明...", - "@addChatDescription": {}, + "commandHint_hug": "傳送一個擁抱表情", + "@commandHint_hug": {}, + "replace": "取代", + "@replace": {}, + "commandHint_googly": "傳送一些瞪眼表情", + "@commandHint_googly": {}, + "importNow": "立即匯入", + "@importNow": {}, + "blockListDescription": "你可以封鎖打擾你的使用者。你不會再收到任何從已封鎖使用者發來的訊息或聊天室邀請。", + "@blockListDescription": {}, + "blockedUsers": "已封鎖的使用者", + "@blockedUsers": {}, + "block": "封鎖", + "@block": {}, + "discover": "發現", + "@discover": {}, + "alwaysUse24HourFormat": "false", + "@alwaysUse24HourFormat": { + "description": "Set to true to always display time of day in 24 hour format." + }, + "sender": "傳送者", + "@sender": {}, + "voiceCall": "語音通話", + "@voiceCall": {}, + "blockUsername": "無視使用者名稱", + "@blockUsername": {}, + "noBackupWarning": "警告!如果不啟用聊天室備份,您將失去對加密訊息的訪問。強烈建議在登出前先啟用聊天室備份。", + "@noBackupWarning": {}, + "addChatOrSubSpace": "新增聊天室或子空間", + "@addChatOrSubSpace": {}, + "thisDevice": "這個裝置:", + "@thisDevice": {}, + "separateChatTypes": "分開私訊和群組", + "@separateChatTypes": { + "type": "text", + "placeholders": {} + }, + "commandHint_markasdm": "將給定的 Matrix ID 標示為直接訊息房間", + "@commandHint_markasdm": {}, + "commandHint_html": "傳送 HTML 格式的文字", + "@commandHint_html": { + "type": "text", + "description": "Usage hint for the command /html" + }, + "commandHint_send": "傳送文字", + "@commandHint_send": { + "type": "text", + "description": "Usage hint for the command /send" + }, + "emoteKeyboardNoRecents": "最近使用的表情將顯示在這裡...", + "@emoteKeyboardNoRecents": { + "type": "text", + "placeholders": {} + }, + "noChatDescriptionYet": "尚未建立聊天室描述。", + "@noChatDescriptionYet": {}, + "optionalRedactReason": "(非必填)收回此訊息的原因...", + "@optionalRedactReason": {}, + "dehydrateWarning": "此操作不能反悔。請確保安全地存儲備份文件。", + "@dehydrateWarning": {}, + "hydrateTorLong": "上次在 TOR 上匯出會話了嗎?快速匯入它已繼續使用聊天室。", + "@hydrateTorLong": {}, + "hydrate": "從備份文件恢復", + "@hydrate": {}, + "locationDisabledNotice": "位置服務被停用。請啟用它們以能夠分享您的位置。", + "@locationDisabledNotice": { + "type": "text", + "placeholders": {} + }, + "noMatrixServer": "{server1} 不是 Matrix 服務器,改用 {server2} 嗎?", + "@noMatrixServer": { + "type": "text", + "placeholders": { + "server1": {}, + "server2": {} + } + }, + "addToBundle": "新增到套組", + "@addToBundle": {}, + "bundleName": "套組名稱", + "@bundleName": {}, + "pleaseEnterYourPin": "請輸入您的密碼", + "@pleaseEnterYourPin": { + "type": "text", + "placeholders": {} + }, + "redactedByBecause": "由 {username} 編輯,原因:「{reason}」", + "@redactedByBecause": { + "type": "text", + "placeholders": { + "username": {}, + "reason": {} + } + }, + "saveFile": "儲存檔案", + "@saveFile": { + "type": "text", + "placeholders": {} + }, + "publish": "發布", + "@publish": {}, + "hasKnocked": "🚪 {user} 敲門了", "@hasKnocked": { "placeholders": { "user": {} } }, - "@publish": {}, - "@openLinkInBrowser": {}, - "@commandHint_react": { + "unlockOldMessages": "解鎖舊消息", + "@unlockOldMessages": {}, + "callingAccountDetails": "允許 FluffyChat 使用原生 Android 撥號應用程式。", + "@callingAccountDetails": {}, + "noOtherDevicesFound": "未找到其他裝置", + "@noOtherDevicesFound": {}, + "noUsersFoundWithQuery": "很遺憾,找不到與「{query}」相符的使用者。請檢查是否有打錯字。", + "@noUsersFoundWithQuery": { "type": "text", - "description": "Usage hint for the command /react" + "placeholders": { + "query": {} + } }, - "@commandHint_me": { - "type": "text", - "description": "Usage hint for the command /me" + "publicLink": "公開網址", + "@publicLink": {}, + "dehydrate": "匯出會話並清除裝置", + "@dehydrate": {}, + "dehydrateTor": "TOR 使用者:匯出會話", + "@dehydrateTor": {}, + "reopenChat": "重新開啟聊天室", + "@reopenChat": {}, + "widgetNameError": "請提供一個顯示名稱。", + "@widgetNameError": {}, + "yourGlobalUserIdIs": "您的全域使用者ID是: ", + "@yourGlobalUserIdIs": {}, + "startFirstChat": "開始您的第一次聊天室", + "@startFirstChat": {}, + "experimentalVideoCalls": "實驗性視訊通話", + "@experimentalVideoCalls": {}, + "youAcceptedTheInvitation": "👍 您接受了邀請", + "@youAcceptedTheInvitation": {}, + "storeSecurlyOnThisDevice": "在此裝置上安全存儲", + "@storeSecurlyOnThisDevice": {}, + "countFiles": "{count} 個文件", + "@countFiles": { + "placeholders": { + "count": {} + } }, - "@messageInfo": {}, - "@disableEncryptionWarning": {}, - "@directChat": {}, + "screenSharingDetail": "您正在 FuffyChat 中分享您的螢幕", + "@screenSharingDetail": {}, + "wrongPinEntered": "輸入的密碼錯誤! {seconds} 秒後再試一次......", "@wrongPinEntered": { "type": "text", "placeholders": { "seconds": {} } }, - "sendTypingNotifications": "傳送「輸入中」通知", - "@sendTypingNotifications": {}, - "@inviteGroupChat": {}, - "@appearOnTop": {}, - "@invitePrivateChat": {}, - "@foregroundServiceRunning": {}, - "@voiceCall": {}, - "@createNewSpace": { - "type": "text", - "placeholders": {} - }, - "importEmojis": "匯入表情包", - "@importEmojis": {}, - "@wasDirectChatDisplayName": { - "type": "text", + "archiveRoomDescription": "聊天室將被移動到存檔中。其他使用者將能看到您已離開聊天室。", + "@archiveRoomDescription": {}, + "banUserDescription": "該使用者將被禁止進入聊天室,直到他們被解封之前都無法再次進入聊天室。", + "@banUserDescription": {}, + "searchChatsRooms": "搜尋 #chats, @users...", + "@searchChatsRooms": {}, + "decline": "拒絕", + "@decline": {}, + "sendReadReceipts": "傳送已讀回條", + "@sendReadReceipts": {}, + "formattedMessagesDescription": "使用 markdown 顯示豐富的訊息內容,如粗體文字。", + "@formattedMessagesDescription": {}, + "verifyOtherDevice": "🔐 驗證其他裝置", + "@verifyOtherDevice": {}, + "youInvitedUser": "📩 您邀請了 {user}", + "@youInvitedUser": { "placeholders": { - "oldDisplayName": {} + "user": {} } }, - "@noChatDescriptionYet": {}, - "@removeFromBundle": {}, - "confirmMatrixId": "如需要刪除你的帳戶,請確認你的Matrix ID。", - "@confirmMatrixId": {}, - "@learnMore": {}, - "notAnImage": "不是圖片檔案。", - "@notAnImage": {}, - "@users": {}, - "@openGallery": {}, - "@chatDescriptionHasBeenChanged": {}, - "@newGroup": {}, - "@bundleName": {}, - "@dehydrateTor": {}, - "@removeFromSpace": {}, - "@commandHint_op": { - "type": "text", - "description": "Usage hint for the command /op" - }, - "@roomUpgradeDescription": {}, - "@scanQrCode": {}, - "@pleaseEnterANumber": {}, + "pinMessage": "釘選到房間", + "@pinMessage": {}, + "youKicked": "👞 您踢出了 {user}", "@youKicked": { "placeholders": { "user": {} } }, - "@profileNotFound": {}, + "users": "使用者", + "@users": {}, + "pleaseChoose": "請選擇", + "@pleaseChoose": { + "type": "text", + "placeholders": {} + }, + "youRejectedTheInvitation": "您拒絕了邀請", + "@youRejectedTheInvitation": {}, + "enterRoom": "進入房間", + "@enterRoom": {}, + "allSpaces": "所有空間", + "@allSpaces": {}, + "indexedDbErrorLong": "預設情況下,私密模式不啟用消息存儲。\n請訪問\n - about:config\n - 將 dom.indexedDB.privateBrowsing.enabled 設定為 true\n否則,無法運行 FluffyChat。", + "@indexedDbErrorLong": {}, + "youKickedAndBanned": "🙅 您踢出並封鎖了 {user}", + "@youKickedAndBanned": { + "placeholders": { + "user": {} + } + }, + "user": "使用者", + "@user": {}, + "custom": "自訂", + "@custom": {}, + "hidePresences": "隱藏狀態列表?", + "@hidePresences": {}, + "signInWithPassword": "使用密碼登入", + "@signInWithPassword": {}, + "setColorTheme": "設定顏色主題:", + "@setColorTheme": {}, + "makeAdminDescription": "一旦您讓這個使用者成為管理員,您可能無法撤銷此操作,因為他們將擁有與您相同的權限。", + "@makeAdminDescription": {}, + "createGroupAndInviteUsers": "建立群組並邀請使用者", + "@createGroupAndInviteUsers": {}, + "groupCanBeFoundViaSearch": "可以透過搜尋找到群組", + "@groupCanBeFoundViaSearch": {}, + "pleaseEnterYourCurrentPassword": "請輸入您當前的密碼", + "@pleaseEnterYourCurrentPassword": {}, + "widgetCustom": "自訂", + "@widgetCustom": {}, + "createGroup": "建立群組", + "@createGroup": {}, + "enterSpace": "進入空間", + "@enterSpace": {}, + "shareLocation": "分享位置", + "@shareLocation": { + "type": "text", + "placeholders": {} + }, + "widgetVideo": "影片", + "@widgetVideo": {}, + "redactMessageDescription": "該訊息將對此對話中的所有參與者收回。這不能被反悔。", + "@redactMessageDescription": {}, + "removeFromBundle": "從此套組中移除", + "@removeFromBundle": {}, + "widgetName": "名稱", + "@widgetName": {}, + "jump": "跳轉", "@jump": {}, + "commandHint_unignore": "取消無視已提供的 Matrix ID", + "@commandHint_unignore": {}, + "commandHint_markasgroup": "標示為群組", + "@commandHint_markasgroup": {}, + "commandHint_me": "描述自己", + "@commandHint_me": { + "type": "text", + "description": "Usage hint for the command /me" + }, + "commandHint_plain": "傳送未格式化的文字", + "@commandHint_plain": { + "type": "text", + "description": "Usage hint for the command /plain" + }, + "commandHint_react": "以反應的形式傳送回覆", + "@commandHint_react": { + "type": "text", + "description": "Usage hint for the command /react" + }, + "createNewSpace": "新建空間", + "@createNewSpace": { + "type": "text", + "placeholders": {} + }, + "allRooms": "所有群組聊天室", + "@allRooms": { + "type": "text", + "placeholders": {} + }, + "chatPermissions": "聊天室權限", + "@chatPermissions": {}, + "customEmojisAndStickersBody": "新增或分享可在任何聊天室中使用的自訂表情符號或貼圖。", + "@customEmojisAndStickersBody": {}, + "errorObtainingLocation": "取得位置錯誤:{error}", + "@errorObtainingLocation": { + "type": "text", + "placeholders": { + "error": {} + } + }, + "hideRedactedMessages": "隱藏被刪除的訊息", + "@hideRedactedMessages": {}, + "hideInvalidOrUnknownMessageFormats": "隱藏無效或未知的訊息格式", + "@hideInvalidOrUnknownMessageFormats": {}, + "dehydrateTorLong": "對 TOR 使用者,建議在關閉窗口前匯出會話。", + "@dehydrateTorLong": {}, + "hydrateTor": "TOR 使用者:匯入會話", + "@hydrateTor": {}, + "messagesStyle": "訊息樣式:", + "@messagesStyle": {}, + "shareInviteLink": "分享邀請網址", + "@shareInviteLink": {}, + "scanQrCode": "掃描 QR 碼", + "@scanQrCode": {}, + "openVideoCamera": "打開錄影", + "@openVideoCamera": { + "type": "text", + "placeholders": {} + }, + "oneClientLoggedOut": "您的一個客戶端已登出", + "@oneClientLoggedOut": {}, + "addAccount": "新增帳號", + "@addAccount": {}, + "editBundlesForAccount": "為此帳號編輯套組", + "@editBundlesForAccount": {}, + "openInMaps": "在地圖中打開", + "@openInMaps": { + "type": "text", + "placeholders": {} + }, + "serverRequiresEmail": "該伺服器需要驗證您的註冊電子郵件地址。", + "@serverRequiresEmail": {}, + "or": "或", + "@or": { + "type": "text", + "placeholders": {} + }, + "hideMemberChangesInPublicChatsBody": "若有人加入或離開公開聊天室,將不在聊天室時間軸顯示,以提升資訊可讀性。", + "@hideMemberChangesInPublicChatsBody": {}, + "overview": "概觀", + "@overview": {}, + "notifyMeFor": "通知我", + "@notifyMeFor": {}, + "passwordRecoverySettings": "恢復密碼設定", + "@passwordRecoverySettings": {}, + "redactedBy": "由 {username} 編輯", + "@redactedBy": { + "type": "text", + "placeholders": { + "username": {} + } + }, + "recoveryKey": "恢復金鑰", + "@recoveryKey": {}, + "spaceName": "空間名稱", + "@spaceName": { + "type": "text", + "placeholders": {} + }, + "synchronizingPleaseWait": "正在同步... 請稍候。", + "@synchronizingPleaseWait": { + "type": "text", + "placeholders": {} + }, + "messageInfo": "訊息資訊", + "@messageInfo": {}, + "removeFromSpace": "從空間中移除", + "@removeFromSpace": {}, + "addToSpaceDescription": "選擇一個空間將此聊天室加入。", + "@addToSpaceDescription": {}, + "pleaseEnterRecoveryKeyDescription": "要解鎖您的舊訊息,請輸入在之前的會話中生成的恢復密鑰。您的恢復密鑰不是您的密碼。", + "@pleaseEnterRecoveryKeyDescription": {}, + "videoWithSize": "影片({size})", + "@videoWithSize": { + "type": "text", + "placeholders": { + "size": {} + } + }, + "emojis": "表情符號", + "@emojis": {}, + "placeCall": "發起通話", + "@placeCall": {}, + "unsupportedAndroidVersion": "不支持的Android版本", + "@unsupportedAndroidVersion": {}, + "videoCallsBetaWarning": "請注意,視訊通話目前處於測試階段。它們可能不會按預期工作,或者在所有平台上都不工作。", + "@videoCallsBetaWarning": {}, + "widgetUrlError": "這不是一個有效的URL。", + "@widgetUrlError": {}, + "nextAccount": "下一個帳戶", + "@nextAccount": {}, + "previousAccount": "上一個帳戶", + "@previousAccount": {}, + "addWidget": "新增小工具", + "@addWidget": {}, + "errorAddingWidget": "新增小工具時發生錯誤。", + "@errorAddingWidget": {}, + "youJoinedTheChat": "您加入了聊天室", + "@youJoinedTheChat": {}, + "youBannedUser": "您封鎖了 {user}", + "@youBannedUser": { + "placeholders": { + "user": {} + } + }, + "youHaveWithdrawnTheInvitationFor": "您已收回對 {user} 的邀請", + "@youHaveWithdrawnTheInvitationFor": { + "placeholders": { + "user": {} + } + }, + "youInvitedBy": "📩 您被 {user} 邀請", + "@youInvitedBy": { + "placeholders": { + "user": {} + } + }, + "youUnbannedUser": "您解除封鎖了 {user}", + "@youUnbannedUser": { + "placeholders": { + "user": {} + } + }, + "youInvitedToBy": "📩 您通過網址被邀請至:\n{alias}", + "@youInvitedToBy": { + "placeholders": { + "alias": {} + } + }, + "callingPermissions": "通話權限", + "@callingPermissions": {}, + "callingAccount": "通話帳戶", + "@callingAccount": {}, + "appearOnTop": "顯示在最上層", + "@appearOnTop": {}, + "newGroup": "新群組", + "@newGroup": {}, + "newSpace": "新空間", + "@newSpace": {}, + "numChats": "{number} 個聊天室", + "@numChats": { + "type": "number", + "placeholders": { + "number": {} + } + }, + "hideUnimportantStateEvents": "隱藏不重要的狀態事件", + "@hideUnimportantStateEvents": {}, + "doNotShowAgain": "不再顯示", + "@doNotShowAgain": {}, + "encryptThisChat": "加密此聊天室", + "@encryptThisChat": {}, + "sorryThatsNotPossible": "抱歉......這是不可能的", + "@sorryThatsNotPossible": {}, + "profileNotFound": "在伺服器上找不到該使用者。可能是連接問題或該使用者不存在。", + "@profileNotFound": {}, + "invite": "邀請", + "@invite": {}, + "invitePrivateChat": "📨 邀請私人聊天室", + "@invitePrivateChat": {}, + "removeDevicesDescription": "您將從這個裝置登出,並將不再能夠接收消息。", + "@removeDevicesDescription": {}, + "unbanUserDescription": "如果該使用者嘗試,他們將能夠再次進入聊天室。", + "@unbanUserDescription": {}, + "kickUserDescription": "該使用者被踢出聊天室,但未被禁止。在公開聊天室中,該使用者可以隨時重新加入。", + "@kickUserDescription": {}, + "pushNotificationsNotAvailable": "推送通知不可用", + "@pushNotificationsNotAvailable": {}, + "learnMore": "了解更多", + "@learnMore": {}, + "nothingFound": "什麼都沒找到......", + "@nothingFound": {}, + "startConversation": "開始對話", + "@startConversation": {}, + "databaseMigrationBody": "請稍候。這可能需要一點時間。", + "@databaseMigrationBody": {}, + "pleaseChooseAStrongPassword": "請選擇一個強密碼", + "@pleaseChooseAStrongPassword": {}, + "passwordIsWrong": "您輸入的密碼錯誤", + "@passwordIsWrong": {}, + "publicChatAddresses": "公開聊天室地址", + "@publicChatAddresses": {}, + "userRole": "使用者角色", + "@userRole": {}, + "minimumPowerLevel": "{level} 是最低權限等級。", + "@minimumPowerLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "leaveEmptyToClearStatus": "留空以清除您的狀態。", + "@leaveEmptyToClearStatus": {}, + "select": "選擇", + "@select": {}, + "files": "文件", + "@files": {}, + "forwardMessageTo": "將訊息轉發至 {roomName}?", + "@forwardMessageTo": { + "type": "text", + "placeholders": { + "roomName": {} + } + }, + "sendTypingNotificationsDescription": "聊天室中的其他參與者可以看到您正在輸入新訊息。", + "@sendTypingNotificationsDescription": {}, + "verifyOtherDeviceDescription": "當您驗證另一個裝置時,這些裝置可以交換密鑰,提升您的整體安全性。💪 當您開始驗證時,一個彈出視窗將在兩個裝置上的應用程式中出現。在那裡,您將看到一系列的表情符號或數字,您需要相互比較。在開始驗證之前最好有兩個裝置在手邊。🤳", + "@verifyOtherDeviceDescription": {}, + "acceptedKeyVerification": "{sender} 接受了密鑰驗證", + "@acceptedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "completedKeyVerification": "{sender} 完成了密鑰驗證", + "@completedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "isReadyForKeyVerification": "{sender} 已準備好進行密鑰驗證", + "@isReadyForKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "thereAreCountUsersBlocked": "目前有 {count} 名使用者被封鎖。", + "@thereAreCountUsersBlocked": { + "type": "text", + "count": {} + }, + "knockRestricted": "敲門受限", + "@knockRestricted": {}, + "appLockDescription": "未使用時以密碼鎖定應用程式", + "@appLockDescription": {}, + "globalChatId": "全球聊天室 ID", + "@globalChatId": {}, + "accessAndVisibility": "訪問權限和可見性", + "@accessAndVisibility": {}, + "accessAndVisibilityDescription": "誰被允許加入此聊天室以及如何發現聊天室。", + "@accessAndVisibilityDescription": {}, + "calls": "通話", + "@calls": {}, + "chatDescription": "聊天室描述", + "@chatDescription": {}, + "chatDescriptionHasBeenChanged": "聊天室描述已變更", + "@chatDescriptionHasBeenChanged": {}, + "tryAgain": "再試一次", + "@tryAgain": {}, + "pleaseEnterRecoveryKey": "請輸入您的恢復金鑰:", + "@pleaseEnterRecoveryKey": {}, + "directChat": "私訊", + "@directChat": {}, + "register": "註冊", + "@register": { + "type": "text", + "placeholders": {} + }, + "setAsCanonicalAlias": "設為主要別名", + "@setAsCanonicalAlias": { + "type": "text", + "placeholders": {} + }, + "setChatDescription": "設定聊天室描述", + "@setChatDescription": {}, + "groupName": "群組名稱", + "@groupName": {}, + "searchForUsers": "搜尋 @users...", + "@searchForUsers": {}, + "inviteGroupChat": "📨 邀請群組聊天室", + "@inviteGroupChat": {}, + "setTheme": "設定主題:", + "@setTheme": {}, + "knocking": "敲門", + "@knocking": {}, + "sessionLostBody": "您的會話已丟失。請將此錯誤報告給開發人員,網址為 {url}。錯誤訊息為:{error}", + "@sessionLostBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "swipeRightToLeftToReply": "向右滑至左以回覆", + "@swipeRightToLeftToReply": {}, + "hideRedactedMessagesBody": "如果有人收回一條訊息,該訊息將不再在聊天室中顯示。", + "@hideRedactedMessagesBody": {}, + "link": "網址", + "@link": {}, + "obtainingLocation": "正在取得位置…", + "@obtainingLocation": { + "type": "text", + "placeholders": {} + }, + "oopsPushError": "哎呀!設定推送通知時不幸發生錯誤。", + "@oopsPushError": { + "type": "text", + "placeholders": {} + }, + "removeYourAvatar": "移除您的頭像", + "@removeYourAvatar": { + "type": "text", + "placeholders": {} + }, + "singlesignon": "單一登入", + "@singlesignon": { + "type": "text", + "placeholders": {} + }, + "presenceStyle": "目前狀態:", + "@presenceStyle": { + "type": "text", + "placeholders": {} + }, + "presencesToggle": "顯示其他使用者的狀態訊息", + "@presencesToggle": { + "type": "text", + "placeholders": {} + }, + "spaceIsPublic": "空間是公開的", + "@spaceIsPublic": { + "type": "text", + "placeholders": {} + }, + "dismiss": "解散", + "@dismiss": {}, + "reactedWith": "{sender} 以 {reaction} 回應", "@reactedWith": { "type": "text", "placeholders": { @@ -2154,87 +2464,304 @@ "reaction": {} } }, - "@sorryThatsNotPossible": {}, - "@videoWithSize": { - "type": "text", + "confirmEventUnpin": "您確定要永久取消釘選該事件嗎?", + "@confirmEventUnpin": {}, + "switchToAccount": "切換到帳戶 {number}", + "@switchToAccount": { + "type": "number", "placeholders": { - "size": {} + "number": {} } }, - "@shareInviteLink": {}, - "@commandHint_markasdm": {}, - "@recoveryKeyLost": {}, - "cuddleContent": "{senderName}摟抱您", - "@cuddleContent": { - "type": "text", - "placeholders": { - "senderName": {} - } - }, - "@deviceKeys": {}, - "@emoteKeyboardNoRecents": { - "type": "text", - "placeholders": {} - }, - "@setTheme": {}, - "@youJoinedTheChat": {}, - "@openVideoCamera": { - "type": "text", - "placeholders": {} - }, - "@markAsRead": {}, - "@widgetName": {}, - "@errorAddingWidget": {}, - "commandHint_hug": "發送一個擁抱表情", - "@commandHint_hug": {}, - "replace": "取代", - "@replace": {}, - "@oopsPushError": { - "type": "text", - "placeholders": {} - }, - "@youUnbannedUser": { + "widgetEtherpad": "文字筆記", + "@widgetEtherpad": {}, + "noOneCanJoin": "沒有人可以加入", + "@noOneCanJoin": {}, + "userWouldLikeToChangeTheChat": "{user} 想要加入聊天室。", + "@userWouldLikeToChangeTheChat": { "placeholders": { "user": {} } }, - "@newSpace": {}, - "@emojis": {}, - "@pleaseEnterYourPin": { + "noPublicLinkHasBeenCreatedYet": "尚未建立公開網址", + "@noPublicLinkHasBeenCreatedYet": {}, + "saveKeyManuallyDescription": "通過觸發系統分享對話框或剪貼板手動保存此密鑰。", + "@saveKeyManuallyDescription": {}, + "storeInAndroidKeystore": "存儲在 Android KeyStore", + "@storeInAndroidKeystore": {}, + "storeInAppleKeyChain": "存儲在 Apple KeyChain", + "@storeInAppleKeyChain": {}, + "foregroundServiceRunning": "當前景服務正在運行時會顯示此通知。", + "@foregroundServiceRunning": {}, + "screenSharingTitle": "螢幕分享", + "@screenSharingTitle": {}, + "wasDirectChatDisplayName": "空的聊天室(原名稱為 {oldDisplayName} )", + "@wasDirectChatDisplayName": { + "type": "text", + "placeholders": { + "oldDisplayName": {} + } + }, + "otherCallingPermissions": "麥克風、相機和其他 FluffyChat 權限", + "@otherCallingPermissions": {}, + "disableEncryptionWarning": "出於安全原因,您不能在之前已加密的聊天室中停用加密。", + "@disableEncryptionWarning": {}, + "deviceKeys": "裝置密鑰:", + "@deviceKeys": {}, + "fileIsTooBigForServer": "伺服器報告該文件太大,無法傳送。", + "@fileIsTooBigForServer": {}, + "fileHasBeenSavedAt": "文件已保存在 {path}", + "@fileHasBeenSavedAt": { + "type": "text", + "placeholders": { + "path": {} + } + }, + "jumpToLastReadMessage": "跳至最後讀取的訊息", + "@jumpToLastReadMessage": {}, + "openLinkInBrowser": "在瀏覽器中開啟連結", + "@openLinkInBrowser": {}, + "reportErrorDescription": "😭 哦不。出了些問題。如果您願意,可以將此錯誤報告給開發者。", + "@reportErrorDescription": {}, + "readUpToHere": "讀到這裡", + "@readUpToHere": {}, + "report": "報告", + "@report": {}, + "pleaseEnterANumber": "請輸入大於 0 的數字", + "@pleaseEnterANumber": {}, + "roomUpgradeDescription": "將使用新版本聊天室來重新建立聊天室。所有本聊天室的參與者都會收到通知,他們都需要換到新的聊天室裡。若您想知道有關新版本的更多資訊,請前往 https://spec.matrix.org/latest/rooms/", + "@roomUpgradeDescription": {}, + "wrongRecoveryKey": "抱歉......這似乎不是正確的恢復密鑰。", + "@wrongRecoveryKey": {}, + "passwordsDoNotMatch": "密碼不匹配", + "@passwordsDoNotMatch": {}, + "publicSpaces": "公共空間", + "@publicSpaces": {}, + "subspace": "子空間", + "@subspace": {}, + "initAppError": "初始化應用時發生錯誤", + "@initAppError": {}, + "canceledKeyVerification": "{sender} 取消了密鑰驗證", + "@canceledKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "startedKeyVerification": "{sender} 開始了密鑰驗證", + "@startedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "transparent": "透明", + "@transparent": {}, + "incomingMessages": "收到的訊息", + "@incomingMessages": {}, + "databaseMigrationTitle": "資料庫已最佳化", + "@databaseMigrationTitle": {}, + "restoreSessionBody": "應用程式現在嘗試從備份中恢復您的會話。請將此錯誤報告給開發人員,網址為 {url}。錯誤訊息為:{error}", + "@restoreSessionBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "stickers": "貼圖", + "@stickers": {}, + "joinSpace": "加入空間", + "@joinSpace": {}, + "noMoreChatsFound": "沒有更多聊天室了...", + "@noMoreChatsFound": {}, + "commandHint_op": "設定給定使用者的權限等級(預設:50)", + "@commandHint_op": { + "type": "text", + "description": "Usage hint for the command /op" + }, + "customEmojisAndStickers": "自訂表情符號和貼圖", + "@customEmojisAndStickers": {}, + "locationPermissionDeniedNotice": "位置權限被拒絕。請授予它們以能夠分享您的位置。", + "@locationPermissionDeniedNotice": { "type": "text", "placeholders": {} }, - "@pleaseChoose": { - "type": "text", - "placeholders": {} - }, - "commandHint_googly": "發送一些瞪眼表情", - "@commandHint_googly": {}, - "@pleaseTryAgainLaterOrChooseDifferentServer": {}, - "@createGroup": {}, - "@hydrateTorLong": {}, - "@time": {}, - "@custom": {}, - "@noBackupWarning": {}, - "@storeInSecureStorageDescription": {}, - "@openChat": {}, - "@kickUserDescription": {}, - "importNow": "立即匯入", - "@importNow": {}, - "@pinMessage": {}, - "@invite": {}, + "inviteContactToGroupQuestion": "您想邀請 {contact} 加入 「{groupName}」 聊天室嗎?", + "@inviteContactToGroupQuestion": {}, + "enableMultiAccounts": "(實驗性功能)在此裝置上啟用多個帳號", "@enableMultiAccounts": {}, - "@indexedDbErrorTitle": {}, + "hideMemberChangesInPublicChats": "在公開聊天室中隱藏成員變動", + "@hideMemberChangesInPublicChats": {}, + "recoveryKeyLost": "遺失恢復金鑰?", + "@recoveryKeyLost": {}, + "sendAsText": "以文字傳送", + "@sendAsText": { + "type": "text" + }, + "sendSticker": "傳送貼圖", + "@sendSticker": { + "type": "text", + "placeholders": {} + }, + "unverified": "尚未驗證", + "@unverified": {}, + "time": "時間", + "@time": {}, + "chatCanBeDiscoveredViaSearchOnServer": "可以透過在 {server} 上的搜尋發現聊天室", + "@chatCanBeDiscoveredViaSearchOnServer": { + "type": "text", + "placeholders": { + "server": {} + } + }, + "commandHint_sendraw": "傳送原始 json", + "@commandHint_sendraw": {}, + "newPassword": "新密碼", + "@newPassword": {}, + "createNewAddress": "建立新地址", + "@createNewAddress": {}, + "searchIn": "在聊天室「{chat}」中搜尋......", + "@searchIn": { + "type": "text", + "placeholders": { + "chat": {} + } + }, + "searchMore": "搜尋更多......", + "@searchMore": {}, + "gallery": "畫廊", + "@gallery": {}, + "databaseBuildErrorBody": "無法建立 SQLite 資料庫。應用程式目前嘗試使用遺留資料庫。請將此錯誤報告給開發人員,網址為 {url}。錯誤訊息為:{error}", + "@databaseBuildErrorBody": { + "type": "text", + "placeholders": { + "url": {}, + "error": {} + } + }, + "sendReadReceiptsDescription": "聊天室中的其他參與者可以看到您已讀取一條訊息。", + "@sendReadReceiptsDescription": {}, + "formattedMessages": "格式化訊息", + "@formattedMessages": {}, + "restricted": "受限", + "@restricted": {}, + "goToSpace": "前往空間:{space}", + "@goToSpace": { + "type": "text", + "space": {} + }, + "markAsUnread": "標示為未讀", + "@markAsUnread": {}, + "noDatabaseEncryption": "此平台不支援資料庫加密", + "@noDatabaseEncryption": {}, + "messageType": "訊息類型", + "@messageType": {}, + "openGallery": "開啟畫廊", + "@openGallery": {}, + "markAsRead": "標示為已讀", + "@markAsRead": {}, + "reportUser": "舉報使用者", + "@reportUser": {}, + "unsupportedAndroidVersionLong": "此功能需要較新的 Android 版本。請檢查更新或 Lineage OS 支持。", "@unsupportedAndroidVersionLong": {}, - "@storeSecurlyOnThisDevice": {}, - "@screenSharingDetail": {}, - "@placeCall": {}, - "blockListDescription": "你可以封鎖打擾你的使用者。你不會再收到任何從已封鎖使用者發來的訊息或聊天室邀請。", - "@blockListDescription": {}, - "blockedUsers": "已封鎖的使用者", - "@blockedUsers": {}, - "block": "封鎖", - "@block": {}, - "discover": "探索", - "@discover": {} + "emailOrUsername": "電子郵件或使用者名", + "@emailOrUsername": {}, + "indexedDbErrorTitle": "私密模式問題", + "@indexedDbErrorTitle": {}, + "widgetJitsi": "Jitsi Meet", + "@widgetJitsi": {}, + "usersMustKnock": "使用者必須敲門", + "@usersMustKnock": {}, + "knock": "敲門", + "@knock": {}, + "storeInSecureStorageDescription": "將恢復密鑰存儲在此裝置的安全存儲中。", + "@storeInSecureStorageDescription": {}, + "appearOnTopDetails": "允許應用程式顯示在最上層(如果您已將 Fluffychat 設定為通話帳戶則不需要)", + "@appearOnTopDetails": {}, + "whyIsThisMessageEncrypted": "為什麼這條訊息無法讀取?", + "@whyIsThisMessageEncrypted": {}, + "noKeyForThisMessage": "如果訊息是在您登入此裝置之前傳送的,就可能會發生這種情況。\n\n也有可能是傳送者已經封鎖了您的裝置,或者網絡連接出了問題。\n\n如果您能在另一個會話中讀取該訊息,那麼您可以從中轉移訊息!前往設定 > 裝置,並確保您的裝置已相互驗證。當您下次打開房間且兩個會話都在前景時,密鑰將自動傳輸。\n\n不想在登出或切換裝置時丟失密鑰?請確保您已在設定中啟用了聊天室備份。", + "@noKeyForThisMessage": {}, + "newSpaceDescription": "空間允許您整合您的聊天室並建立私人或公開社群。", + "@newSpaceDescription": {}, + "pleaseTryAgainLaterOrChooseDifferentServer": "請稍後再試,或選擇不同的伺服器。", + "@pleaseTryAgainLaterOrChooseDifferentServer": {}, + "signInWith": "使用 {provider} 登入", + "@signInWith": { + "type": "text", + "placeholders": { + "provider": {} + } + }, + "invalidInput": "無效的輸入!", + "@invalidInput": {}, + "verifyOtherUser": "🔐 驗證其他使用者", + "@verifyOtherUser": {}, + "verifyOtherUserDescription": "如果您驗證了另一個使用者,您可以確定您真正與誰通信。💪\n\n當您開始驗證時,您和另一個使用者將在應用程式中看到一個彈出視窗。在那裡,您將看到一系列的表情符號或數字,您需要相互比較。\n\n最好的方式是見面或開始視訊通話。👭", + "@verifyOtherUserDescription": {}, + "requestedKeyVerification": "{sender} 請求了密鑰驗證", + "@requestedKeyVerification": { + "type": "text", + "placeholders": { + "sender": {} + } + }, + "commandHint_ignore": "無視已提供的 Matrix ID", + "@commandHint_ignore": {}, + "countChatsAndCountParticipants": "{chats} 個聊天室和 {participants} 位參與者", + "@countChatsAndCountParticipants": { + "type": "text", + "placeholders": { + "chats": {}, + "participants": {} + } + }, + "joinedChats": "已加入的聊天室", + "@joinedChats": {}, + "unread": "未讀", + "@unread": {}, + "space": "空間", + "@space": {}, + "spaces": "空間", + "@spaces": {}, + "start": "開始", + "@start": {}, + "openChat": "開啟聊天室", + "@openChat": {}, + "unreadChatsInApp": "{appname}:{unread} 未讀聊天室", + "@unreadChatsInApp": { + "type": "text", + "placeholders": { + "appname": {}, + "unread": {} + } + }, + "adminLevel": "{level} - 管理員", + "@adminLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "userLevel": "{level} - 用戶", + "@userLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "moderatorLevel": "{level} - 管理員", + "@moderatorLevel": { + "type": "text", + "placeholders": { + "level": {} + } + }, + "invitedBy": "📩 由 {user} 邀請", + "@invitedBy": { + "placeholders": { + "user": {} + } + } } diff --git a/docs/index.html b/docs/index.html index 0d82ae518..b0205811c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -38,7 +38,7 @@ Buy Me a Coffee at ko-fi.com - diff --git a/ios/Gemfile.lock b/ios/Gemfile.lock index aaaffc7b4..3854e9409 100644 --- a/ios/Gemfile.lock +++ b/ios/Gemfile.lock @@ -156,8 +156,8 @@ GEM trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.2.8) - strscan (>= 3.0.9) + rexml (3.3.6) + strscan rouge (2.0.7) ruby2_keywords (0.0.4) rubyzip (2.3.0) diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 9413c6971..7f38bb254 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,7 +1,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index 669075097..cbc47a8c8 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -19,7 +19,7 @@ abstract class AppConfig { static double fontSizeFactor = 1; static const Color chatColor = primaryColor; static Color? colorSchemeSeed = primaryColor; - static const double messageFontSize = 15.75; + static const double messageFontSize = 16.0; static const bool allowOtherHomeservers = true; static const bool enableRegistration = true; static const double toolbarMaxHeight = 315.0; @@ -57,6 +57,8 @@ abstract class AppConfig { static const String supportUrl = 'https://www.pangeachat.com/faqs'; static const String termsOfServiceUrl = 'https://www.pangeachat.com/terms-of-service'; + // static const String changelogUrl = + // 'https://github.com/krille-chan/fluffychat/blob/main/CHANGELOG.md'; //Pangea# static final Uri newIssueUrl = Uri( scheme: 'https', @@ -153,10 +155,10 @@ abstract class AppConfig { _defaultHomeserver = json['default_homeserver']; } if (json['privacy_url'] is String) { - _webBaseUrl = json['privacy_url']; + _privacyUrl = json['privacy_url']; } if (json['web_base_url'] is String) { - _privacyUrl = json['web_base_url']; + _webBaseUrl = json['web_base_url']; } if (json['render_html'] is bool) { // #Pangea diff --git a/lib/config/routes.dart b/lib/config/routes.dart index d9c7a70f7..0ee135e7d 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -26,9 +26,7 @@ import 'package:fluffychat/pages/settings_notifications/settings_notifications.d import 'package:fluffychat/pages/settings_password/settings_password.dart'; import 'package:fluffychat/pages/settings_security/settings_security.dart'; import 'package:fluffychat/pages/settings_style/settings_style.dart'; -import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; import 'package:fluffychat/pangea/guard/p_vguard.dart'; -import 'package:fluffychat/pangea/pages/analytics/student_analytics/student_analytics.dart'; import 'package:fluffychat/pangea/pages/find_partner/find_partner.dart'; import 'package:fluffychat/pangea/pages/p_user_age/p_user_age.dart'; import 'package:fluffychat/pangea/pages/settings_learning/settings_learning.dart'; @@ -76,7 +74,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - const HomeserverPicker(), + const HomeserverPicker(addMultiAccount: false), ), redirect: loggedInRedirect, routes: [ @@ -162,17 +160,17 @@ abstract class AppRoutes { ), routes: [ // #Pangea - GoRoute( - path: 'mylearning', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const StudentAnalyticsPage( - selectedView: BarChartViewSelection.messages, - ), - ), - redirect: loggedOutRedirect, - ), + // GoRoute( + // path: 'mylearning', + // pageBuilder: (context, state) => defaultPageBuilder( + // context, + // state, + // const StudentAnalyticsPage( + // selectedView: BarChartViewSelection.messages, + // ), + // ), + // redirect: loggedOutRedirect, + // ), // GoRoute( // path: 'analytics', // pageBuilder: (context, state) => defaultPageBuilder( @@ -351,13 +349,15 @@ abstract class AppRoutes { // redirect: loggedOutRedirect, // pageBuilder: (context, state) => defaultPageBuilder( // context, - // const HomeserverPicker(), + // state, + // const HomeserverPicker(addMultiAccount: true), // ), // routes: [ // GoRoute( // path: 'login', // pageBuilder: (context, state) => defaultPageBuilder( // context, + // state, // const Login(), // ), // redirect: loggedOutRedirect, diff --git a/lib/config/themes.dart b/lib/config/themes.dart index 90dfefe68..fb75a0aee 100644 --- a/lib/config/themes.dart +++ b/lib/config/themes.dart @@ -78,9 +78,6 @@ abstract class FluffyThemes { ? Typography.material2018().black.merge(fallbackTextTheme) : Typography.material2018().white.merge(fallbackTextTheme) : null, - snackBarTheme: const SnackBarThemeData( - behavior: SnackBarBehavior.floating, - ), dividerColor: brightness == Brightness.light ? Colors.blueGrey.shade50 : Colors.blueGrey.shade900, @@ -95,11 +92,10 @@ abstract class FluffyThemes { ), inputDecorationTheme: InputDecorationTheme( border: OutlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), + borderRadius: BorderRadius.circular(AppConfig.borderRadius), ), contentPadding: const EdgeInsets.all(12), - filled: true, + filled: false, ), appBarTheme: AppBarTheme( toolbarHeight: FluffyThemes.isColumnMode(context) ? 72 : 56, @@ -118,13 +114,6 @@ abstract class FluffyThemes { systemNavigationBarColor: colorScheme.surface, ), ), - textButtonTheme: TextButtonThemeData( - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), - ), - ), - ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( side: BorderSide( @@ -149,9 +138,6 @@ abstract class FluffyThemes { elevation: 0, padding: const EdgeInsets.all(16), textStyle: const TextStyle(fontSize: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(AppConfig.borderRadius), - ), ), ), // #Pangea diff --git a/lib/pages/bootstrap/bootstrap_dialog.dart b/lib/pages/bootstrap/bootstrap_dialog.dart index e1c4cde71..b816d2fc1 100644 --- a/lib/pages/bootstrap/bootstrap_dialog.dart +++ b/lib/pages/bootstrap/bootstrap_dialog.dart @@ -88,6 +88,7 @@ class BootstrapDialogState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); _wipe ??= widget.wipe; final buttons = []; Widget body = const CircularProgressIndicator.adaptive(); @@ -119,7 +120,7 @@ class BootstrapDialogState extends State { backgroundColor: Colors.transparent, child: Icon( Icons.info_outlined, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), subtitle: Text(L10n.of(context)!.chatBackupDescription), @@ -144,7 +145,7 @@ class BootstrapDialogState extends State { CheckboxListTile.adaptive( contentPadding: const EdgeInsets.symmetric(horizontal: 8.0), value: _storeInSecureStorage, - activeColor: Theme.of(context).colorScheme.primary, + activeColor: theme.colorScheme.primary, onChanged: (b) { setState(() { _storeInSecureStorage = b; @@ -158,7 +159,7 @@ class BootstrapDialogState extends State { CheckboxListTile.adaptive( contentPadding: const EdgeInsets.symmetric(horizontal: 8.0), value: _recoveryKeyCopied, - activeColor: Theme.of(context).colorScheme.primary, + activeColor: theme.colorScheme.primary, onChanged: (b) { FluffyShare.share(key!, context); setState(() => _recoveryKeyCopied = true); @@ -241,7 +242,7 @@ class BootstrapDialogState extends State { const EdgeInsets.symmetric(horizontal: 8.0), trailing: Icon( Icons.info_outlined, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), subtitle: Text( L10n.of(context)!.pleaseEnterRecoveryKeyDescription, @@ -261,10 +262,11 @@ class BootstrapDialogState extends State { decoration: InputDecoration( contentPadding: const EdgeInsets.all(16), hintStyle: TextStyle( - fontFamily: - Theme.of(context).textTheme.bodyLarge?.fontFamily, + fontFamily: theme.textTheme.bodyLarge?.fontFamily, ), - hintText: L10n.of(context)!.recoveryKey, + prefixIcon: const Icon(Icons.key_outlined), + labelText: L10n.of(context)!.recoveryKey, + hintText: 'Es** **** **** ****', errorText: _recoveryKeyInputError, errorMaxLines: 2, ), @@ -272,9 +274,8 @@ class BootstrapDialogState extends State { const SizedBox(height: 16), ElevatedButton.icon( style: ElevatedButton.styleFrom( - foregroundColor: - Theme.of(context).colorScheme.onPrimary, - backgroundColor: Theme.of(context).colorScheme.primary, + foregroundColor: theme.colorScheme.onPrimary, + backgroundColor: theme.colorScheme.primary, ), icon: _recoveryKeyInputLoading ? const CircularProgressIndicator.adaptive() @@ -386,10 +387,8 @@ class BootstrapDialogState extends State { const SizedBox(height: 16), ElevatedButton.icon( style: ElevatedButton.styleFrom( - backgroundColor: - Theme.of(context).colorScheme.errorContainer, - foregroundColor: - Theme.of(context).colorScheme.onErrorContainer, + backgroundColor: theme.colorScheme.errorContainer, + foregroundColor: theme.colorScheme.onErrorContainer, ), icon: const Icon(Icons.delete_outlined), label: Text(L10n.of(context)!.recoveryKeyLost), diff --git a/lib/pages/chat/add_widget_tile_view.dart b/lib/pages/chat/add_widget_tile_view.dart index d7ac53ef2..18153faba 100644 --- a/lib/pages/chat/add_widget_tile_view.dart +++ b/lib/pages/chat/add_widget_tile_view.dart @@ -59,7 +59,7 @@ class AddWidgetTileView extends StatelessWidget { ), ), ), - ButtonBar( + OverflowBar( children: [ TextButton( onPressed: controller.addWidget, diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 69617b271..12fc40af1 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -3,6 +3,7 @@ import 'dart:developer'; import 'dart:io'; import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:collection/collection.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:file_picker/file_picker.dart'; @@ -124,7 +125,7 @@ class ChatController extends State Timeline? timeline; - String? readMarkerEventId; + late final String readMarkerEventId; String get roomId => widget.room.id; @@ -254,23 +255,22 @@ class ChatController extends State // void requestHistory([_]) async { Future requestHistory() async { if (timeline == null) return; - // Pangea# if (!timeline!.canRequestHistory) return; + // Pangea# Logs().v('Requesting history...'); - await timeline!.requestHistory(historyCount: _loadHistoryCount); + await timeline?.requestHistory(historyCount: _loadHistoryCount); } void requestFuture() async { final timeline = this.timeline; if (timeline == null) return; - if (!timeline.canRequestFuture) return; Logs().v('Requesting future...'); final mostRecentEventId = timeline.events.first.eventId; await timeline.requestFuture(historyCount: _loadHistoryCount); setReadMarker(eventId: mostRecentEventId); } - void _updateScrollController() { + void updateScrollController() { if (!mounted) { return; } @@ -289,7 +289,7 @@ class ChatController extends State } } - void _loadDraft() async { + void loadDraft() async { final prefs = await SharedPreferences.getInstance(); final draft = widget.shareText ?? prefs.getString('draft_$roomId'); if (draft != null && draft.isNotEmpty) { @@ -299,17 +299,18 @@ class ChatController extends State @override void initState() { - scrollController.addListener(_updateScrollController); - inputFocus.addListener(_inputFocusListener); + scrollController.addListener(updateScrollController); + inputFocus.addListener(inputFocusListener); - _loadDraft(); + loadDraft(); super.initState(); - _displayChatDetailsColumn = ValueNotifier( + displayChatDetailsColumn = ValueNotifier( Matrix.of(context).store.getBool(SettingKeys.displayChatDetailsColumn) ?? false, ); sendingClient = Matrix.of(context).client; + readMarkerEventId = room.hasNewMessages ? room.fullyRead : ''; WidgetsBinding.instance.addObserver(this); // #Pangea if (!mounted) return; @@ -333,32 +334,48 @@ class ChatController extends State await Matrix.of(context).client.roomsLoading; }); // Pangea# - _tryLoadTimeline(); + tryLoadTimeline(); if (kIsWeb) { onFocusSub = html.window.onFocus.listen((_) => setReadMarker()); } } - void _tryLoadTimeline() async { + void tryLoadTimeline() async { final initialEventId = widget.eventId; loadTimelineFuture = _getTimeline(); try { await loadTimelineFuture; if (initialEventId != null) scrollToEventId(initialEventId); - final fullyRead = room.fullyRead; - if (fullyRead.isEmpty) { - setReadMarker(); - return; + var readMarkerEventIndex = readMarkerEventId.isEmpty + ? -1 + : timeline!.events + .where((e) => e.isVisibleInGui || e.eventId == readMarkerEventId) + .toList() + .indexWhere((e) => e.eventId == readMarkerEventId); + + // Read marker is existing but not found in first events. Try a single + // requestHistory call before opening timeline on event context: + if (readMarkerEventId.isNotEmpty && readMarkerEventIndex == -1) { + await timeline?.requestHistory(historyCount: _loadHistoryCount); + readMarkerEventIndex = timeline!.events + .where((e) => e.isVisibleInGui || e.eventId == readMarkerEventId) + .toList() + .indexWhere((e) => e.eventId == readMarkerEventId); } - if (timeline?.events.any((event) => event.eventId == fullyRead) ?? - false) { - Logs().v('Scroll up to visible event', fullyRead); - setReadMarker(); + + if (readMarkerEventIndex > 1) { + Logs().v('Scroll up to visible event', readMarkerEventId); + scrollToEventId(readMarkerEventId, highlightEvent: false); return; + } else if (readMarkerEventId.isNotEmpty && readMarkerEventIndex == -1) { + showScrollUpMaterialBanner(readMarkerEventId); } + + // Mark room as read on first visit if requirements are fulfilled + setReadMarker(); + if (!mounted) return; - _showScrollUpMaterialBanner(fullyRead); } catch (e, s) { ErrorReporter(context, 'Unable to load timeline').onErrorCallback(e, s); rethrow; @@ -371,12 +388,13 @@ class ChatController extends State scrollUpBannerEventId = null; }); - void _showScrollUpMaterialBanner(String eventId) => setState(() { + void showScrollUpMaterialBanner(String eventId) => setState(() { scrollUpBannerEventId = eventId; }); void updateView() { if (!mounted) return; + setReadMarker(); setState(() {}); } @@ -385,11 +403,6 @@ class ChatController extends State int? animateInEventIndex; void onInsert(int i) { - if (timeline?.events[i].status == EventStatus.synced) { - final index = timeline!.events.firstIndexWhereNotError; - if (i == index) setReadMarker(eventId: timeline?.events[i].eventId); - } - // setState will be called by updateView() anyway animateInEventIndex = i; } @@ -414,6 +427,7 @@ class ChatController extends State eventContextId = null; } try { + timeline?.cancelSubscriptions(); timeline = await room.getTimeline( onUpdate: updateView, eventContextId: eventContextId, @@ -421,9 +435,9 @@ class ChatController extends State ); // #Pangea if (visibleEvents.length < 10 && timeline != null) { - int prevNumEvents = timeline!.events.length; + var prevNumEvents = timeline!.events.length; await requestHistory(); - int numRequests = 0; + var numRequests = 0; while (timeline!.events.length > prevNumEvents && visibleEvents.length < 10 && numRequests <= 5) { @@ -442,7 +456,7 @@ class ChatController extends State ); if (!mounted) return; if (e is TimeoutException || e is IOException) { - _showScrollUpMaterialBanner(eventContextId!); + showScrollUpMaterialBanner(eventContextId!); } } timeline!.requestKeys(onlineKeyBackupOnly: false); @@ -459,12 +473,13 @@ class ChatController extends State setReadMarker(); } - Future? _setReadMarkerFuture; + Future? setReadMarkerFuture; void setReadMarker({String? eventId}) { - if (_setReadMarkerFuture != null) return; + if (setReadMarkerFuture != null) return; if (_scrolledUp) return; if (scrollUpBannerEventId != null) return; + if (eventId == null && !room.hasNewMessages && room.notificationCount == 0) { @@ -477,7 +492,7 @@ class ChatController extends State // Pangea# if (kIsWeb && !Matrix.of(context).webHasFocus) return; // #Pangea - } catch (err, s) { + } catch (err) { return; } // Pangea# @@ -493,13 +508,13 @@ class ChatController extends State Logs().d('Set read marker...', eventId); // ignore: unawaited_futures - _setReadMarkerFuture = timeline + setReadMarkerFuture = timeline .setReadMarker( eventId: eventId, public: AppConfig.sendPublicReadReceipts, ) .then((_) { - _setReadMarkerFuture = null; + setReadMarkerFuture = null; }) // #Pangea .catchError((e, s) { @@ -531,7 +546,7 @@ class ChatController extends State void dispose() { timeline?.cancelSubscriptions(); timeline = null; - inputFocus.removeListener(_inputFocusListener); + inputFocus.removeListener(inputFocusListener); onFocusSub?.cancel(); //#Pangea choreographer.stateListener.close(); @@ -590,7 +605,7 @@ class ChatController extends State }) async { // Pangea# if (sendController.text.trim().isEmpty) return; - _storeInputTimeoutTimer?.cancel(); + storeInputTimeoutTimer?.cancel(); final prefs = await SharedPreferences.getInstance(); prefs.remove('draft_$roomId'); var parseCommands = true; @@ -634,6 +649,22 @@ class ChatController extends State .then( (String? msgEventId) async { // #Pangea + // There's a listen in my_analytics_controller that decides when to auto-update + // analytics based on when / how many messages the logged in user send. This + // stream sends the data for newly sent messages. + if (msgEventId != null) { + pangeaController.myAnalytics.setState( + data: { + 'eventID': msgEventId, + 'eventType': EventTypes.Message, + 'roomID': room.id, + 'originalSent': originalSent, + 'tokensSent': tokensSent, + 'choreo': choreo, + }, + ); + } + if (previousEdit != null) { pangeaEditingEvent = previousEdit; } @@ -661,7 +692,7 @@ class ChatController extends State setState(() { sendController.text = pendingText; - _inputTextIsEmpty = pendingText.isEmpty; + inputTextIsEmpty = pendingText.isEmpty; replyEvent = null; editEvent = null; pendingText = ''; @@ -800,18 +831,11 @@ class ChatController extends State builder: (c) => const RecordingDialog(), ); if (result == null) return; - // #Pangea - // enable web recording - // final audioFile = File(result.path); - // final file = MatrixAudioFile( - // bytes: audioFile.readAsBytesSync(), - // name: audioFile.path, - // ); + final audioFile = XFile(result.path); final file = MatrixAudioFile( - bytes: result.bytes, - name: result.path, + bytes: await audioFile.readAsBytes(), + name: result.fileName ?? audioFile.path, ); - // Pangea# await room.sendFileEvent( file, inReplyTo: replyEvent, @@ -841,12 +865,9 @@ class ChatController extends State }); } - // #Pangea - // void hideEmojiPicker() { - void hideEmojiPicker({bool closeOverlay = false}) { - if (closeOverlay) { - MatrixState.pAnyState.closeOverlay(); - } + void hideEmojiPicker() { + // #Pangea + clearSelectedEvents(); // Pangea# setState(() => showEmojiPicker = false); } @@ -868,7 +889,7 @@ class ChatController extends State setState(() => showEmojiPicker = !showEmojiPicker); } - void _inputFocusListener() { + void inputFocusListener() { if (showEmojiPicker && inputFocus.hasFocus) { emojiPickerType = EmojiPickerType.keyboard; setState(() => showEmojiPicker = false); @@ -882,7 +903,7 @@ class ChatController extends State ); } - String _getSelectedEventString() { + String getSelectedEventString() { var copyString = ''; if (selectedEvents.length == 1) { return selectedEvents.first @@ -900,7 +921,7 @@ class ChatController extends State } void copyEventsAction() { - Clipboard.setData(ClipboardData(text: _getSelectedEventString())); + Clipboard.setData(ClipboardData(text: getSelectedEventString())); setState(() { showEmojiPicker = false; // #Pangea @@ -1108,7 +1129,7 @@ class ChatController extends State } else { Matrix.of(context).shareContent = { 'msgtype': 'm.text', - 'body': _getSelectedEventString(), + 'body': getSelectedEventString(), }; } setState(() => selectedEvents.clear()); @@ -1144,10 +1165,16 @@ class ChatController extends State String eventId, { bool highlightEvent = true, }) async { - final eventIndex = timeline!.events - .where((event) => event.isVisibleInGui) - .toList() - .indexWhere((e) => e.eventId == eventId); + final foundEvent = + timeline!.events.firstWhereOrNull((event) => event.eventId == eventId); + + final eventIndex = foundEvent == null + ? -1 + : timeline!.events + .where((event) => event.isVisibleInGui || event.eventId == eventId) + .toList() + .indexOf(foundEvent); + if (eventIndex == -1) { setState(() { timeline = null; @@ -1173,7 +1200,7 @@ class ChatController extends State duration: FluffyThemes.animationDuration, preferPosition: AutoScrollPosition.middle, ); - _updateScrollController(); + updateScrollController(); } void scrollDown() async { @@ -1466,18 +1493,18 @@ class ChatController extends State ); } - Timer? _storeInputTimeoutTimer; - static const Duration _storeInputTimeout = Duration(milliseconds: 500); + Timer? storeInputTimeoutTimer; + static const storeInputTimeout = Duration(milliseconds: 500); void onInputBarChanged(String text) { - if (_inputTextIsEmpty != text.isEmpty) { + if (inputTextIsEmpty != text.isEmpty) { setState(() { - _inputTextIsEmpty = text.isEmpty; + inputTextIsEmpty = text.isEmpty; }); } - _storeInputTimeoutTimer?.cancel(); - _storeInputTimeoutTimer = Timer(_storeInputTimeout, () async { + storeInputTimeoutTimer?.cancel(); + storeInputTimeoutTimer = Timer(storeInputTimeout, () async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('draft_$roomId', text); }); @@ -1516,7 +1543,7 @@ class ChatController extends State } } - bool _inputTextIsEmpty = true; + var inputTextIsEmpty = true; bool get isArchived => {Membership.leave, Membership.ban}.contains(room.membership); @@ -1583,7 +1610,7 @@ class ChatController extends State }); // #Pangea - MessageTextSelection textSelection = MessageTextSelection(); + final textSelection = MessageTextSelection(); void showToolbar( PangeaMessageEvent pangeaMessageEvent, { @@ -1592,9 +1619,10 @@ class ChatController extends State Event? prevEvent, }) { if (![ - MessageTypes.Text, - MessageTypes.Audio, - ].contains(pangeaMessageEvent.event.messageType)) { + MessageTypes.Text, + MessageTypes.Audio, + ].contains(pangeaMessageEvent.event.messageType) || + pangeaMessageEvent.event.redacted) { return; } @@ -1632,7 +1660,7 @@ class ChatController extends State context: context, child: overlayEntry, transformTargetId: "", - backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(100), + backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(150), closePrevOverlay: MatrixState.pangeaController.subscriptionController.isSubscribed, position: OverlayPositionEnum.centered, @@ -1645,69 +1673,63 @@ class ChatController extends State } // Pangea# - late final ValueNotifier _displayChatDetailsColumn; + late final ValueNotifier displayChatDetailsColumn; void toggleDisplayChatDetailsColumn() async { await Matrix.of(context).store.setBool( SettingKeys.displayChatDetailsColumn, - !_displayChatDetailsColumn.value, + !displayChatDetailsColumn.value, ); - _displayChatDetailsColumn.value = !_displayChatDetailsColumn.value; + displayChatDetailsColumn.value = !displayChatDetailsColumn.value; } @override - Widget build(BuildContext context) => Row( - children: [ - Expanded( - child: ChatView(this), - ), - AnimatedSize( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - child: ValueListenableBuilder( - valueListenable: _displayChatDetailsColumn, - builder: (context, displayChatDetailsColumn, _) { - if (!FluffyThemes.isThreeColumnMode(context) || - room.membership != Membership.join || - !displayChatDetailsColumn) { - return const SizedBox( - height: double.infinity, - width: 0, - ); - } - return Container( - width: FluffyThemes.columnWidth, - clipBehavior: Clip.hardEdge, - decoration: BoxDecoration( - border: Border( - left: BorderSide( - width: 1, - color: Theme.of(context).dividerColor, - ), - ), - ), - child: ChatDetails( - roomId: roomId, - embeddedCloseButton: IconButton( - icon: const Icon(Icons.close), - onPressed: toggleDisplayChatDetailsColumn, - ), - ), + Widget build(BuildContext context) { + final theme = Theme.of(context); + return Row( + children: [ + Expanded( + child: ChatView(this), + ), + AnimatedSize( + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + child: ValueListenableBuilder( + valueListenable: displayChatDetailsColumn, + builder: (context, displayChatDetailsColumn, _) { + if (!FluffyThemes.isThreeColumnMode(context) || + room.membership != Membership.join || + !displayChatDetailsColumn) { + return const SizedBox( + height: double.infinity, + width: 0, ); - }, - ), + } + return Container( + width: FluffyThemes.columnWidth, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + border: Border( + left: BorderSide( + width: 1, + color: theme.dividerColor, + ), + ), + ), + child: ChatDetails( + roomId: roomId, + embeddedCloseButton: IconButton( + icon: const Icon(Icons.close), + onPressed: toggleDisplayChatDetailsColumn, + ), + ), + ); + }, ), - ], - ); + ), + ], + ); + } } enum EmojiPickerType { reaction, keyboard } - -extension on List { - int get firstIndexWhereNotError { - if (isEmpty) return 0; - final index = indexWhere((event) => !event.status.isError); - if (index == -1) return length; - return index; - } -} diff --git a/lib/pages/chat/chat_app_bar_list_tile.dart b/lib/pages/chat/chat_app_bar_list_tile.dart index 1e0ec8259..1ca0c5fba 100644 --- a/lib/pages/chat/chat_app_bar_list_tile.dart +++ b/lib/pages/chat/chat_app_bar_list_tile.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_linkify/flutter_linkify.dart'; -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/utils/url_launcher.dart'; class ChatAppBarListTile extends StatelessWidget { @@ -11,6 +10,8 @@ class ChatAppBarListTile extends StatelessWidget { final Widget? trailing; final void Function()? onTap; + static const double fixedHeight = 40.0; + const ChatAppBarListTile({ super.key, this.leading, @@ -21,40 +22,42 @@ class ChatAppBarListTile extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); final leading = this.leading; final trailing = this.trailing; - final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; - return InkWell( - onTap: onTap, - child: Row( - children: [ - if (leading != null) leading, - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4.0), - child: Linkify( - text: title, - options: const LinkifyOptions(humanize: false), - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, + return SizedBox( + height: fixedHeight, + child: InkWell( + onTap: onTap, + child: Row( + children: [ + if (leading != null) leading, + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: Linkify( + text: title, + options: const LinkifyOptions(humanize: false), + maxLines: 1, overflow: TextOverflow.ellipsis, - fontSize: fontSize, + style: TextStyle( + color: theme.colorScheme.onSurfaceVariant, + overflow: TextOverflow.ellipsis, + fontSize: 14, + ), + linkStyle: TextStyle( + color: theme.colorScheme.onSurfaceVariant, + fontSize: 14, + decoration: TextDecoration.underline, + decorationColor: theme.colorScheme.onSurfaceVariant, + ), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), - linkStyle: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, - fontSize: fontSize, - decoration: TextDecoration.underline, - decorationColor: - Theme.of(context).colorScheme.onSurfaceVariant, - ), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), ), - ), - if (trailing != null) trailing, - ], + if (trailing != null) trailing, + ], + ), ), ); } diff --git a/lib/pages/chat/chat_emoji_picker.dart b/lib/pages/chat/chat_emoji_picker.dart index e7bf9c744..c016da6b9 100644 --- a/lib/pages/chat/chat_emoji_picker.dart +++ b/lib/pages/chat/chat_emoji_picker.dart @@ -13,96 +13,90 @@ class ChatEmojiPicker extends StatelessWidget { @override Widget build(BuildContext context) { - final ThemeData theme = Theme.of(context); - // #Pangea - return Material( - // Pangea# - child: AnimatedContainer( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - clipBehavior: Clip.hardEdge, - decoration: const BoxDecoration(), - height: controller.showEmojiPicker - ? MediaQuery.of(context).size.height / 2 - : 0, - child: controller.showEmojiPicker - ? DefaultTabController( - length: 2, - child: Column( - children: [ - TabBar( - tabs: [ - Tab(text: L10n.of(context)!.emojis), - Tab(text: L10n.of(context)!.stickers), - ], - ), - Expanded( - child: TabBarView( - children: [ - EmojiPicker( - onEmojiSelected: controller.onEmojiSelected, - onBackspacePressed: controller.emojiPickerBackspace, - config: Config( - emojiViewConfig: EmojiViewConfig( - noRecents: const NoRecent(), - backgroundColor: Theme.of(context) - .colorScheme - .onInverseSurface, - ), - bottomActionBarConfig: - const BottomActionBarConfig( - enabled: false, - ), - categoryViewConfig: CategoryViewConfig( - backspaceColor: theme.colorScheme.primary, - iconColor: - theme.colorScheme.primary.withOpacity(0.5), - iconColorSelected: theme.colorScheme.primary, - indicatorColor: theme.colorScheme.primary, - ), - skinToneConfig: SkinToneConfig( - dialogBackgroundColor: Color.lerp( - theme.colorScheme.surface, - theme.colorScheme.primaryContainer, - 0.75, - )!, - indicatorColor: theme.colorScheme.onSurface, - ), + final theme = Theme.of(context); + return AnimatedContainer( + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + clipBehavior: Clip.hardEdge, + decoration: const BoxDecoration(), + height: controller.showEmojiPicker + ? MediaQuery.of(context).size.height / 2 + : 0, + child: controller.showEmojiPicker + ? DefaultTabController( + length: 2, + child: Column( + children: [ + TabBar( + tabs: [ + Tab(text: L10n.of(context)!.emojis), + Tab(text: L10n.of(context)!.stickers), + ], + ), + Expanded( + child: TabBarView( + children: [ + EmojiPicker( + onEmojiSelected: controller.onEmojiSelected, + onBackspacePressed: controller.emojiPickerBackspace, + config: Config( + emojiViewConfig: EmojiViewConfig( + noRecents: const NoRecent(), + backgroundColor: + theme.colorScheme.onInverseSurface, + ), + bottomActionBarConfig: const BottomActionBarConfig( + enabled: false, + ), + categoryViewConfig: CategoryViewConfig( + backspaceColor: theme.colorScheme.primary, + iconColor: + theme.colorScheme.primary.withOpacity(0.5), + iconColorSelected: theme.colorScheme.primary, + indicatorColor: theme.colorScheme.primary, + ), + skinToneConfig: SkinToneConfig( + dialogBackgroundColor: Color.lerp( + theme.colorScheme.surface, + theme.colorScheme.primaryContainer, + 0.75, + )!, + indicatorColor: theme.colorScheme.onSurface, ), ), - StickerPickerDialog( - room: controller.room, - onSelected: (sticker) { - controller.room.sendEvent( - { - 'body': sticker.body, - 'info': sticker.info ?? {}, - 'url': sticker.url.toString(), - }, - type: EventTypes.Sticker, - ); - controller.hideEmojiPicker(); - }, - ), - ], - ), + ), + StickerPickerDialog( + room: controller.room, + onSelected: (sticker) { + controller.room.sendEvent( + { + 'body': sticker.body, + 'info': sticker.info ?? {}, + 'url': sticker.url.toString(), + }, + type: EventTypes.Sticker, + ); + controller.hideEmojiPicker(); + }, + ), + ], ), - // #Pangea - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: FloatingActionButton( - onPressed: controller.hideEmojiPicker, - shape: const CircleBorder(), - mini: true, - child: const Icon(Icons.close), - ), + ), + // #Pangea + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: FloatingActionButton( + onPressed: controller.hideEmojiPicker, + shape: const CircleBorder(), + mini: true, + child: const Icon(Icons.close), ), - // Pangea# - ], - ), - ) - : null, - ), + ), + // Pangea# + ], + ), + ) + : null, ); } } diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index c4558d44b..ac155144d 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -205,8 +205,7 @@ class ChatEventList extends StatelessWidget { .any((e) => e.eventId == event.eventId), timeline: controller.timeline!, displayReadMarker: - controller.readMarkerEventId == event.eventId && - controller.timeline?.allowNewEvent == false, + i > 0 && controller.readMarkerEventId == event.eventId, nextEvent: i + 1 < events.length ? events[i + 1] : null, previousEvent: i > 0 ? events[i - 1] : null, avatarPresenceBackgroundColor: diff --git a/lib/pages/chat/chat_input_row.dart b/lib/pages/chat/chat_input_row.dart index bee8a1af8..cc931ef12 100644 --- a/lib/pages/chat/chat_input_row.dart +++ b/lib/pages/chat/chat_input_row.dart @@ -1,6 +1,5 @@ import 'package:animations/animations.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pages/chat/input_bar.dart'; import 'package:fluffychat/pangea/choreographer/widgets/send_button.dart'; import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/utils/platform_infos.dart'; @@ -12,6 +11,7 @@ import 'package:matrix/matrix.dart'; import '../../config/themes.dart'; import 'chat.dart'; +import 'input_bar.dart'; class ChatInputRow extends StatelessWidget { final ChatController controller; @@ -20,6 +20,7 @@ class ChatInputRow extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); if (controller.showEmojiPicker && controller.emojiPickerType == EmojiPickerType.reaction) { return const SizedBox.shrink(); @@ -66,7 +67,7 @@ class ChatInputRow extends StatelessWidget { height: height, child: TextButton( style: TextButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.error, + foregroundColor: theme.colorScheme.error, ), onPressed: controller.deleteErrorEventsAction, child: Row( @@ -139,15 +140,7 @@ class ChatInputRow extends StatelessWidget { duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, height: height, - // #Pangea - // width: - // controller.sendController.text.isEmpty ? height : 0, - width: controller.sendController.text.isEmpty && - controller.pangeaController.permissionsController - .showChatInputAddButton(controller.roomId) - ? height - : 0, - // Pangea# + width: controller.sendController.text.isEmpty ? height : 0, alignment: Alignment.center, clipBehavior: Clip.hardEdge, decoration: const BoxDecoration(), @@ -224,21 +217,6 @@ class ChatInputRow extends StatelessWidget { contentPadding: const EdgeInsets.all(0), ), ), - if (controller.room - .getImagePacks(ImagePackUsage.sticker) - .isNotEmpty) - PopupMenuItem( - value: 'sticker', - child: ListTile( - leading: const CircleAvatar( - backgroundColor: Colors.orange, - foregroundColor: Colors.white, - child: Icon(Icons.emoji_emotions_outlined), - ), - title: Text(L10n.of(context)!.sendSticker), - contentPadding: const EdgeInsets.all(0), - ), - ), //#Pangea // if (PlatformInfos.isMobile) if (PlatformInfos.isMobile && @@ -260,9 +238,6 @@ class ChatInputRow extends StatelessWidget { ], ), ), - // #Pangea - // ), - // Pangea# Container( height: height, width: height, @@ -303,9 +278,6 @@ class ChatInputRow extends StatelessWidget { ), onPressed: controller.emojiPickerAction, ), - // #Pangea - // ), - // Pangea# ), // #Pangea // if (Matrix.of(context).isMultiAccount && @@ -373,10 +345,8 @@ class ChatInputRow extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(height), ), - backgroundColor: - Theme.of(context).colorScheme.primary, - foregroundColor: - Theme.of(context).colorScheme.onPrimary, + backgroundColor: theme.colorScheme.primary, + foregroundColor: theme.colorScheme.onPrimary, child: const Icon(Icons.mic_none_outlined), ) : @@ -390,11 +360,9 @@ class ChatInputRow extends StatelessWidget { // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(height), // ), - // backgroundColor: Theme.of(context) - // .colorScheme - // .onPrimaryContainer, - // foregroundColor: - // Theme.of(context).colorScheme.onPrimary, + // backgroundColor: + // theme.colorScheme.onPrimaryContainer, + // foregroundColor: theme.colorScheme.onPrimary, // child: const Icon(Icons.send_outlined), // ), // Pangea# diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 83ca6ca27..75cb583d3 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -10,6 +10,7 @@ import 'package:fluffychat/pages/chat/reply_display.dart'; import 'package:fluffychat/pangea/choreographer/widgets/it_bar.dart'; import 'package:fluffychat/pangea/choreographer/widgets/start_igc_button.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; +import 'package:fluffychat/pangea/widgets/animations/gain_points.dart'; import 'package:fluffychat/pangea/widgets/chat/chat_floating_action_button.dart'; import 'package:fluffychat/pangea/widgets/chat/input_bar_wrapper.dart'; import 'package:fluffychat/utils/account_config.dart'; @@ -42,15 +43,11 @@ class ChatView extends StatelessWidget { tooltip: L10n.of(context)!.edit, onPressed: controller.editSelectedEventAction, ), - // #Pangea - if (controller.selectedEvents.length == 1 && - controller.selectedEvents.single.messageType == MessageTypes.Text) - // Pangea# - IconButton( - icon: const Icon(Icons.copy_outlined), - tooltip: L10n.of(context)!.copy, - onPressed: controller.copyEventsAction, - ), + IconButton( + icon: const Icon(Icons.copy_outlined), + tooltip: L10n.of(context)!.copy, + onPressed: controller.copyEventsAction, + ), if (controller.canSaveSelectedEvent) // Use builder context to correctly position the share dialog on iPad Builder( @@ -143,6 +140,7 @@ class ChatView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); if (controller.room.membership == Membership.invite) { showFutureLoadingDialog( context: context, @@ -161,7 +159,7 @@ class ChatView extends StatelessWidget { return PopScope( canPop: controller.selectedEvents.isEmpty && !controller.showEmojiPicker, - onPopInvoked: (pop) async { + onPopInvokedWithResult: (pop, _) async { if (pop) return; if (controller.selectedEvents.isNotEmpty) { controller.clearSelectedEvents(); @@ -178,39 +176,46 @@ class ChatView extends StatelessWidget { builder: (BuildContext context, snapshot) { var appbarBottomHeight = 0.0; if (controller.room.pinnedEventIds.isNotEmpty) { - appbarBottomHeight += 42; + appbarBottomHeight += ChatAppBarListTile.fixedHeight; } if (scrollUpBannerEventId != null) { - appbarBottomHeight += 42; + appbarBottomHeight += ChatAppBarListTile.fixedHeight; } final tombstoneEvent = controller.room.getState(EventTypes.RoomTombstone); if (tombstoneEvent != null) { - appbarBottomHeight += 42; + appbarBottomHeight += ChatAppBarListTile.fixedHeight; } return Scaffold( appBar: AppBar( actionsIconTheme: IconThemeData( color: controller.selectedEvents.isEmpty ? null - : Theme.of(context).colorScheme.primary, + : theme.colorScheme.primary, ), leading: controller.selectMode ? IconButton( icon: const Icon(Icons.close), onPressed: controller.clearSelectedEvents, tooltip: L10n.of(context)!.close, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ) - : UnreadRoomsBadge( - filter: (r) => - r.id != controller.roomId - // #Pangea - && - !r.isAnalyticsRoom, - // Pangea# - badgePosition: BadgePosition.topEnd(end: 8, top: 4), - child: const Center(child: BackButton()), + : StreamBuilder( + stream: Matrix.of(context) + .client + .onSync + .stream + .where((syncUpdate) => syncUpdate.hasRoomUpdate), + builder: (context, _) => UnreadRoomsBadge( + filter: (r) => + r.id != controller.roomId + // #Pangea + && + !r.isAnalyticsRoom, + // Pangea# + badgePosition: BadgePosition.topEnd(end: 8, top: 4), + child: const Center(child: BackButton()), + ), ), titleSpacing: 0, title: ChatAppBarTitle(controller), @@ -236,8 +241,7 @@ class ChatView extends StatelessWidget { if (scrollUpBannerEventId != null) ChatAppBarListTile( leading: IconButton( - color: - Theme.of(context).colorScheme.onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, icon: const Icon(Icons.close), tooltip: L10n.of(context)!.close, onPressed: () { @@ -338,7 +342,7 @@ class ChatView extends StatelessWidget { alignment: Alignment.center, child: Material( clipBehavior: Clip.hardEdge, - color: Theme.of(context) + color: theme .colorScheme // ignore: deprecated_member_use .surfaceVariant, @@ -351,43 +355,16 @@ class ChatView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - // #Pangea - if (controller.room.isRoomAdmin) - TextButton.icon( - style: TextButton.styleFrom( - padding: const EdgeInsets.all( - 16, - ), - foregroundColor: - Theme.of(context) - .colorScheme - .error, - ), - icon: const Icon( - Icons.archive_outlined, - ), - onPressed: - controller.archiveChat, - label: Text( - L10n.of(context)!.archive, - ), - ), - // Pangea# TextButton.icon( style: TextButton.styleFrom( padding: const EdgeInsets.all( 16, ), foregroundColor: - Theme.of(context) - .colorScheme - .error, + theme.colorScheme.error, ), icon: const Icon( - // #Pangea - // Icons.archive_outlined, - Icons.arrow_forward, - // Pangea# + Icons.archive_outlined, ), onPressed: controller.leaveChat, label: Text( @@ -417,18 +394,20 @@ class ChatView extends StatelessWidget { // Column( // mainAxisSize: MainAxisSize.min, // children: [ - // const ConnectionStatusHeader(), - // ITBar( - // choreographer: - // controller.choreographer, - // ), - // ReactionsPicker(controller), - // ReplyDisplay(controller), - // ChatInputRow(controller), - // ChatEmojiPicker(controller), - // ], - // ), + // const ConnectionStatusHeader(), + // // #Pangea + // ITBar( + // choreographer: + // controller.choreographer, + // ), + // // ReactionsPicker(controller), + // // Pangea# + // ReplyDisplay(controller), + // ChatInputRow(controller), // Pangea# + // ChatEmojiPicker(controller), + // ], + // ), ), ), // #Pangea @@ -465,8 +444,18 @@ class ChatView extends StatelessWidget { StartIGCButton( controller: controller, ), - ChatFloatingActionButton( - controller: controller, + Row( + children: [ + PointsGainedAnimation( + gainColor: Theme.of(context) + .colorScheme + .onPrimary, + ), + const SizedBox(width: 100), + ChatFloatingActionButton( + controller: controller, + ), + ], ), ], ), @@ -510,20 +499,18 @@ class ChatView extends StatelessWidget { // Pangea# ], ), - // #Pangea - // if (controller.dragging) - // Container( - // color: Theme.of(context) - // .scaffoldBackgroundColor - // .withOpacity(0.9), - // alignment: Alignment.center, - // child: const Icon( - // Icons.upload_outlined, - // size: 100, - // ), - // ), - // Pangea# ), + // #Pangea + // if (controller.dragging) + // Container( + // color: theme.scaffoldBackgroundColor.withOpacity(0.9), + // alignment: Alignment.center, + // child: const Icon( + // Icons.upload_outlined, + // size: 100, + // ), + // ), + // Pangea# ], ), ); diff --git a/lib/pages/chat/event_info_dialog.dart b/lib/pages/chat/event_info_dialog.dart index 38acdc84c..c930e4b14 100644 --- a/lib/pages/chat/event_info_dialog.dart +++ b/lib/pages/chat/event_info_dialog.dart @@ -28,14 +28,15 @@ class EventInfoDialog extends StatelessWidget { }); String get prettyJson { - const JsonDecoder decoder = JsonDecoder(); - const JsonEncoder encoder = JsonEncoder.withIndent(' '); + const decoder = JsonDecoder(); + const encoder = JsonEncoder.withIndent(' '); final object = decoder.convert(jsonEncode(event.toJson())); return encoder.convert(object); } @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: Text(L10n.of(context)!.messageInfo), @@ -72,14 +73,14 @@ class EventInfoDialog extends StatelessWidget { padding: const EdgeInsets.all(12.0), child: Material( borderRadius: BorderRadius.circular(AppConfig.borderRadius), - color: Theme.of(context).colorScheme.inverseSurface, + color: theme.colorScheme.inverseSurface, child: SingleChildScrollView( padding: const EdgeInsets.all(8), scrollDirection: Axis.horizontal, child: SelectableText( prettyJson, style: TextStyle( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, ), ), ), diff --git a/lib/pages/chat/events/audio_player.dart b/lib/pages/chat/events/audio_player.dart index 8ab4d067a..d848cb6cc 100644 --- a/lib/pages/chat/events/audio_player.dart +++ b/lib/pages/chat/events/audio_player.dart @@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; import 'package:matrix/matrix.dart'; +import 'package:opus_caf_converter_dart/opus_caf_converter_dart.dart'; import 'package:path_provider/path_provider.dart'; import '../../../utils/matrix_sdk_extensions/event_extension.dart'; @@ -95,7 +96,18 @@ class AudioPlayerState extends State { // Pangea# ); file = File('${tempDir.path}/${fileName}_${matrixFile.name}'); + await file.writeAsBytes(matrixFile.bytes); + + if (Platform.isIOS && + matrixFile.mimeType.toLowerCase() == 'audio/ogg') { + Logs().v('Convert ogg audio file for iOS...'); + final convertedFile = File('${file.path}.caf'); + if (await convertedFile.exists() == false) { + OpusCaf().convertOpusToCaf(file.path, convertedFile.path); + } + file = convertedFile; + } } setState(() { @@ -295,6 +307,8 @@ class AudioPlayerState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final statusText = this.statusText ??= _durationString ?? '00:00'; final audioPlayer = this.audioPlayer; return Padding( @@ -397,8 +411,8 @@ class AudioPlayerState extends State { // : Text( // '${audioPlayer.speed.toString()}x', // ), - // backgroundColor: Theme.of(context).colorScheme.secondary, - // textColor: Theme.of(context).colorScheme.onSecondary, + // backgroundColor: theme.colorScheme.secondary, + // textColor: theme.colorScheme.onSecondary, // child: InkWell( // splashColor: widget.color.withAlpha(128), // borderRadius: BorderRadius.circular(64), diff --git a/lib/pages/chat/events/image_bubble.dart b/lib/pages/chat/events/image_bubble.dart index f5219b054..3ee745eeb 100644 --- a/lib/pages/chat/events/image_bubble.dart +++ b/lib/pages/chat/events/image_bubble.dart @@ -67,6 +67,8 @@ class ImageBubble extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final borderRadius = this.borderRadius ?? BorderRadius.circular(AppConfig.borderRadius); return Material( @@ -77,7 +79,7 @@ class ImageBubble extends StatelessWidget { side: BorderSide( color: event.messageType == MessageTypes.Sticker ? Colors.transparent - : Theme.of(context).dividerColor, + : theme.dividerColor, ), ), child: InkWell( diff --git a/lib/pages/chat/events/map_bubble.dart b/lib/pages/chat/events/map_bubble.dart index d9cea7695..b417680bb 100644 --- a/lib/pages/chat/events/map_bubble.dart +++ b/lib/pages/chat/events/map_bubble.dart @@ -21,6 +21,8 @@ class MapBubble extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return ClipRRect( borderRadius: BorderRadius.circular(radius), child: Container( @@ -71,11 +73,10 @@ class MapBubble extends StatelessWidget { child: Text( ' © OpenStreetMap contributors ', style: TextStyle( - color: Theme.of(context).brightness == Brightness.dark + color: theme.brightness == Brightness.dark ? Colors.white : Colors.black, - backgroundColor: - Theme.of(context).appBarTheme.backgroundColor, + backgroundColor: theme.appBarTheme.backgroundColor, ), ), ), diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 4c009e3f4..32208bb5f 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -99,6 +99,8 @@ class Message extends StatelessWidget { } }); // Pangea# + final theme = Theme.of(context); + if (!{ EventTypes.Message, EventTypes.Sticker, @@ -120,7 +122,7 @@ class Message extends StatelessWidget { final ownMessage = event.senderId == client.userID; final alignment = ownMessage ? Alignment.topRight : Alignment.topLeft; // ignore: deprecated_member_use - var color = Theme.of(context).colorScheme.surfaceVariant; + var color = theme.colorScheme.surfaceVariant; final displayTime = event.type == EventTypes.RoomCreate || nextEvent == null || !event.originServerTs.sameEnvironment(nextEvent!.originServerTs); @@ -142,9 +144,8 @@ class Message extends StatelessWidget { previousEvent!.senderId == event.senderId && previousEvent!.originServerTs.sameEnvironment(event.originServerTs); - final textColor = ownMessage - ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.onSurface; + final textColor = + ownMessage ? theme.colorScheme.onPrimary : theme.colorScheme.onSurface; final rowMainAxisAlignment = ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start; @@ -173,7 +174,7 @@ class Message extends StatelessWidget { if (ownMessage) { color = displayEvent.status.isError ? Colors.redAccent - : Theme.of(context).colorScheme.primary; + : theme.colorScheme.primary; } final resetAnimateIn = this.resetAnimateIn; @@ -213,14 +214,10 @@ class Message extends StatelessWidget { borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), color: selected - ? Theme.of(context) - .colorScheme - .secondaryContainer + ? theme.colorScheme.secondaryContainer .withAlpha(100) : highlightMarker - ? Theme.of(context) - .colorScheme - .tertiaryContainer + ? theme.colorScheme.tertiaryContainer .withAlpha(100) : Colors.transparent, ), @@ -304,8 +301,7 @@ class Message extends StatelessWidget { displayname, style: TextStyle( fontSize: 12, - color: (Theme.of(context) - .brightness == + color: (theme.brightness == Brightness.light ? displayname.color : displayname @@ -557,22 +553,20 @@ class Message extends StatelessWidget { ? const EdgeInsets.symmetric(vertical: 8.0) : EdgeInsets.zero, child: Center( - child: Material( - color: displayTime - ? Theme.of(context).colorScheme.surface - : Theme.of(context).colorScheme.surface.withOpacity(0.33), - borderRadius: - BorderRadius.circular(AppConfig.borderRadius / 2), - clipBehavior: Clip.antiAlias, - child: Padding( - padding: const EdgeInsets.only(top: 4.0), - child: Text( - event.originServerTs.localizedTime(context), - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 12 * AppConfig.fontSizeFactor, - color: Theme.of(context).colorScheme.secondary, - ), + child: Padding( + padding: const EdgeInsets.only(top: 4.0), + child: Text( + event.originServerTs.localizedTime(context), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 12 * AppConfig.fontSizeFactor, + color: theme.colorScheme.secondary, + shadows: [ + Shadow( + color: theme.colorScheme.surface, + blurRadius: 3, + ), + ], ), ), ), @@ -619,14 +613,14 @@ class Message extends StatelessWidget { Row( children: [ Expanded( - child: Divider(color: Theme.of(context).colorScheme.primary), + child: Divider(color: theme.colorScheme.primary), ), Container( decoration: BoxDecoration( border: Border.all( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), - color: Theme.of(context).colorScheme.primaryContainer, + color: theme.colorScheme.primaryContainer, borderRadius: BorderRadius.circular(4), ), margin: const EdgeInsets.all(8.0), @@ -635,12 +629,11 @@ class Message extends StatelessWidget { ), child: Text( L10n.of(context)!.readUpToHere, - style: - TextStyle(color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), ), ), Expanded( - child: Divider(color: Theme.of(context).colorScheme.primary), + child: Divider(color: theme.colorScheme.primary), ), ], ), diff --git a/lib/pages/chat/events/message_reactions.dart b/lib/pages/chat/events/message_reactions.dart index 56286cae0..a4b2addbc 100644 --- a/lib/pages/chat/events/message_reactions.dart +++ b/lib/pages/chat/events/message_reactions.dart @@ -108,10 +108,10 @@ class _Reaction extends StatelessWidget { @override Widget build(BuildContext context) { - final textColor = Theme.of(context).brightness == Brightness.dark - ? Colors.white - : Colors.black; - final color = Theme.of(context).colorScheme.surface; + final theme = Theme.of(context); + final textColor = + theme.brightness == Brightness.dark ? Colors.white : Colors.black; + final color = theme.colorScheme.surface; Widget content; if (reactionKey.startsWith('mxc://')) { content = Row( @@ -158,8 +158,8 @@ class _Reaction extends StatelessWidget { border: Border.all( width: 1, color: reacted! - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.primaryContainer, + ? theme.colorScheme.primary + : theme.colorScheme.primaryContainer, ), borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), ), diff --git a/lib/pages/chat/events/reply_content.dart b/lib/pages/chat/events/reply_content.dart index b48f16cd9..08756df33 100644 --- a/lib/pages/chat/events/reply_content.dart +++ b/lib/pages/chat/events/reply_content.dart @@ -26,20 +26,19 @@ class ReplyContent extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final timeline = this.timeline; final displayEvent = timeline != null ? replyEvent.getDisplayEvent(timeline) : replyEvent; final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; final color = ownMessage - ? Theme.of(context).colorScheme.primaryContainer - : Theme.of(context).colorScheme.primary; + ? theme.colorScheme.primaryContainer + : theme.colorScheme.primary; return Material( color: backgroundColor ?? - Theme.of(context) - .colorScheme - .surface - .withOpacity(ownMessage ? 0.2 : 0.33), + theme.colorScheme.surface.withOpacity(ownMessage ? 0.2 : 0.33), borderRadius: borderRadius, child: Row( mainAxisSize: MainAxisSize.min, @@ -80,8 +79,8 @@ class ReplyContent extends StatelessWidget { maxLines: 1, style: TextStyle( color: ownMessage - ? Theme.of(context).colorScheme.onPrimary - : Theme.of(context).colorScheme.onSurface, + ? theme.colorScheme.onPrimary + : theme.colorScheme.onSurface, fontSize: fontSize, ), ), diff --git a/lib/pages/chat/events/state_message.dart b/lib/pages/chat/events/state_message.dart index 0aa5d9dc2..e38f75815 100644 --- a/lib/pages/chat/events/state_message.dart +++ b/lib/pages/chat/events/state_message.dart @@ -12,15 +12,13 @@ class StateMessage extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Center( child: Container( padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), - ), child: Text( event.calcLocalizedBodyFallback( MatrixLocals(L10n.of(context)!), @@ -29,6 +27,12 @@ class StateMessage extends StatelessWidget { style: TextStyle( fontSize: 12 * AppConfig.fontSizeFactor, decoration: event.redacted ? TextDecoration.lineThrough : null, + shadows: [ + Shadow( + color: theme.colorScheme.surface, + blurRadius: 3, + ), + ], ), ), ), diff --git a/lib/pages/chat/events/verification_request_content.dart b/lib/pages/chat/events/verification_request_content.dart index b6ec3fd09..a09f007f7 100644 --- a/lib/pages/chat/events/verification_request_content.dart +++ b/lib/pages/chat/events/verification_request_content.dart @@ -17,6 +17,8 @@ class VerificationRequestContent extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final events = event.aggregatedEvents(timeline, 'm.reference'); final done = events.where((e) => e.type == EventTypes.KeyVerificationDone); final start = @@ -36,10 +38,10 @@ class VerificationRequestContent extends StatelessWidget { padding: const EdgeInsets.all(8), decoration: BoxDecoration( border: Border.all( - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), borderRadius: BorderRadius.circular(AppConfig.borderRadius), - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, ), child: Row( mainAxisSize: MainAxisSize.min, diff --git a/lib/pages/chat/events/video_player.dart b/lib/pages/chat/events/video_player.dart index d76d49576..385f83567 100644 --- a/lib/pages/chat/events/video_player.dart +++ b/lib/pages/chat/events/video_player.dart @@ -70,7 +70,7 @@ class EventVideoPlayerState extends State { autoInitialize: true, ); } - } on Exception catch (e) { + } on IOException catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toLocalizedString(context)), @@ -95,6 +95,8 @@ class EventVideoPlayerState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final hasThumbnail = widget.event.hasThumbnail; final blurHash = (widget.event.infoMap as Map) .tryGet('xyz.amorgan.blurhash') ?? @@ -122,7 +124,7 @@ class EventVideoPlayerState extends State { Center( child: IconButton( style: IconButton.styleFrom( - backgroundColor: Theme.of(context).colorScheme.surface, + backgroundColor: theme.colorScheme.surface, ), icon: _isDownloading ? const SizedBox( diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index aea82a886..c0939f278 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -51,9 +51,6 @@ class InputBar extends StatelessWidget { }); List> getSuggestions(String text) { - // #Pangea - final List> ret = >[]; - // Pangea# if (controller!.selection.baseOffset != controller!.selection.extentOffset || controller!.selection.baseOffset < 0) { @@ -61,9 +58,7 @@ class InputBar extends StatelessWidget { } final searchText = controller!.text.substring(0, controller!.selection.baseOffset); - // #Pangea - // final List> ret = >[]; - // Pangea# + final ret = >[]; const maxResults = 30; final commandMatch = RegExp(r'^/(\w*)$').firstMatch(searchText); @@ -229,6 +224,7 @@ class InputBar extends StatelessWidget { Map suggestion, Client? client, ) { + final theme = Theme.of(context); const size = 30.0; // #Pangea // const padding = EdgeInsets.all(4.0); @@ -253,7 +249,7 @@ class InputBar extends StatelessWidget { hint, maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodySmall, + style: theme.textTheme.bodySmall, ), ], ), @@ -481,6 +477,7 @@ class InputBar extends StatelessWidget { key: controller?.choreographer.inputLayerLinkAndKey.key, // builder: (context, controller, focusNode) => TextField( builder: (context, _, focusNode) => TextField( + enableSuggestions: false, // Pangea# controller: controller, focusNode: focusNode, diff --git a/lib/pages/chat/pinned_events.dart b/lib/pages/chat/pinned_events.dart index 0940a786f..1baa488c5 100644 --- a/lib/pages/chat/pinned_events.dart +++ b/lib/pages/chat/pinned_events.dart @@ -53,6 +53,8 @@ class PinnedEvents extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final pinnedEventIds = controller.room.pinnedEventIds; if (pinnedEventIds.isEmpty) { @@ -71,9 +73,9 @@ class PinnedEvents extends StatelessWidget { ) ?? L10n.of(context)!.loadingPleaseWait, leading: IconButton( - splashRadius: 20, - iconSize: 20, - color: Theme.of(context).colorScheme.onSurfaceVariant, + splashRadius: 18, + iconSize: 18, + color: theme.colorScheme.onSurfaceVariant, icon: const Icon(Icons.push_pin), tooltip: L10n.of(context)!.unpin, onPressed: controller.room.canSendEvent(EventTypes.RoomPinnedEvents) diff --git a/lib/pages/chat/reactions_picker.dart b/lib/pages/chat/reactions_picker.dart index c61dc4f48..fade2a24b 100644 --- a/lib/pages/chat/reactions_picker.dart +++ b/lib/pages/chat/reactions_picker.dart @@ -1,4 +1,3 @@ -import 'package:emoji_proposal/emoji_proposal.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_emojis.dart'; import 'package:fluffychat/pages/chat/chat.dart'; @@ -14,6 +13,8 @@ class ReactionsPicker extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + if (controller.showEmojiPicker) return const SizedBox.shrink(); final display = controller.editEvent == null && controller.replyEvent == null && @@ -30,14 +31,7 @@ class ReactionsPicker extends StatelessWidget { if (!display) { return const SizedBox.shrink(); } - final proposals = proposeEmojis( - controller.selectedEvents.first.plaintextBody, - number: 25, - languageCodes: EmojiProposalLanguageCodes.values.toSet(), - ); - final emojis = proposals.isNotEmpty - ? proposals.map((e) => e.char).toList() - : List.from(AppEmojis.emojis); + final emojis = List.from(AppEmojis.emojis); final allReactionEvents = controller.selectedEvents.first .aggregatedEvents( controller.timeline!, @@ -59,7 +53,7 @@ class ReactionsPicker extends StatelessWidget { Expanded( child: Container( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, borderRadius: const BorderRadius.only( bottomRight: Radius.circular(AppConfig.borderRadius), ), @@ -91,7 +85,7 @@ class ReactionsPicker extends StatelessWidget { width: 36, height: 56, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, shape: BoxShape.circle, ), child: const Icon(Icons.add_outlined), diff --git a/lib/pages/chat/recording_dialog.dart b/lib/pages/chat/recording_dialog.dart index 1540b3405..0d2c2adb6 100644 --- a/lib/pages/chat/recording_dialog.dart +++ b/lib/pages/chat/recording_dialog.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/utils/update_version_dialog.dart'; @@ -8,7 +7,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:http/http.dart' as http; +import 'package:path/path.dart' as path_lib; import 'package:path_provider/path_provider.dart'; import 'package:record/record.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; @@ -16,7 +15,6 @@ import 'package:wakelock_plus/wakelock_plus.dart'; import 'events/audio_player.dart'; class RecordingDialog extends StatefulWidget { - static const String recordingFileType = 'wav'; const RecordingDialog({ super.key, }); @@ -30,10 +28,12 @@ class RecordingDialogState extends State { Duration _duration = Duration.zero; bool error = false; - String? _recordedPath; + final _audioRecorder = AudioRecorder(); final List amplitudeTimeline = []; + String? fileName; + static const int bitRate = 64000; // #Pangea // static const int samplingRate = 44100; @@ -43,14 +43,23 @@ class RecordingDialogState extends State { Future startRecording() async { try { // #Pangea - // enable recording on web - // final tempDir = await getTemporaryDirectory(); - // final path = _recordedPath = - // '${tempDir.path}/recording${DateTime.now().microsecondsSinceEpoch}.${RecordingDialog.recordingFileType}'; - final tempDirPath = kIsWeb ? "." : (await getTemporaryDirectory()).path; - _recordedPath = - '$tempDirPath/recording${DateTime.now().microsecondsSinceEpoch}.${RecordingDialog.recordingFileType}'; + // final codec = kIsWeb + // // Web seems to create webm instead of ogg when using opus encoder + // // which does not play on iOS right now. So we use wav for now: + // ? AudioEncoder.wav + // // Everywhere else we use opus if supported by the platform: + // : await _audioRecorder.isEncoderSupported(AudioEncoder.opus) + // ? AudioEncoder.opus + // : AudioEncoder.aacLc; + const codec = AudioEncoder.wav; // Pangea# + fileName = + 'recording${DateTime.now().microsecondsSinceEpoch}.${codec.fileExtension}'; + String? path; + if (!kIsWeb) { + final tempDir = await getTemporaryDirectory(); + path = path_lib.join(tempDir.path, fileName); + } final result = await _audioRecorder.hasPermission(); if (result != true) { @@ -58,12 +67,13 @@ class RecordingDialogState extends State { return; } await WakelockPlus.enable(); + // #Pangea - final bool isNotError = await showUpdateVersionDialog( + final isNotError = await showUpdateVersionDialog( future: () => // Pangea# + _audioRecorder.start( - path: _recordedPath!, const RecordConfig( bitRate: bitRate, sampleRate: samplingRate, @@ -71,10 +81,9 @@ class RecordingDialogState extends State { autoGain: true, echoCancel: true, noiseSuppress: true, - // #Pangea - encoder: AudioEncoder.wav, - // Pangea# + encoder: codec, ), + path: path ?? '', ), // #Pangea context: context, @@ -119,25 +128,9 @@ class RecordingDialogState extends State { void _stopAndSend() async { _recorderSubscription?.cancel(); - // #Pangea - // await _audioRecorder.stop(); - final outputPath = await _audioRecorder.stop(); - // Pangea# - final path = _recordedPath; + final path = await _audioRecorder.stop(); + if (path == null) throw ('Recording failed!'); - - // #Pangea - Uint8List bytes; - if (kIsWeb) { - if (outputPath == null) throw ('Recording failed!'); - final response = await http.get(Uri.parse(outputPath)); - bytes = response.bodyBytes; - } else { - final audioFile = File(path); - bytes = audioFile.readAsBytesSync(); - } - // Pangea# - const waveCount = AudioPlayerWidget.wavesCount; final step = amplitudeTimeline.length < waveCount ? 1 @@ -151,15 +144,15 @@ class RecordingDialogState extends State { path: path, duration: _duration.inMilliseconds, waveform: waveform, - // #Pangea - bytes: bytes, - // Pangea# + fileName: fileName, ), ); } @override Widget build(BuildContext context) { + final theme = Theme.of(context); + const maxDecibalWidth = 64.0; final time = '${_duration.inMinutes.toString().padLeft(2, '0')}:${(_duration.inSeconds % 60).toString().padLeft(2, '0')}'; @@ -188,7 +181,7 @@ class RecordingDialogState extends State { margin: const EdgeInsets.only(left: 2), width: 4, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, borderRadius: BorderRadius.circular(AppConfig.borderRadius), ), @@ -214,11 +207,7 @@ class RecordingDialogState extends State { child: Text( L10n.of(context)!.cancel.toUpperCase(), style: TextStyle( - color: Theme.of(context) - .textTheme - .bodyMedium - ?.color - ?.withAlpha(150), + color: theme.textTheme.bodyMedium?.color?.withAlpha(150), ), ), ), @@ -238,8 +227,7 @@ class RecordingDialogState extends State { child: Text( L10n.of(context)!.cancel.toUpperCase(), style: TextStyle( - color: - Theme.of(context).textTheme.bodyMedium?.color?.withAlpha(150), + color: theme.textTheme.bodyMedium?.color?.withAlpha(150), ), ), ), @@ -264,35 +252,32 @@ class RecordingResult { final String path; final int duration; final List waveform; - // #Pangea - final Uint8List bytes; - // Pangea# + final String? fileName; const RecordingResult({ required this.path, required this.duration, required this.waveform, - // #Pangea - required this.bytes, - // Pangea# + required this.fileName, }); - - factory RecordingResult.fromJson(Map json) => - RecordingResult( - path: json['path'], - duration: json['duration'], - waveform: List.from(json['waveform']), - // #Pangea - bytes: Uint8List.fromList(json['bytes']), - // Pangea# - ); - - Map toJson() => { - 'path': path, - 'duration': duration, - 'waveform': waveform, - // #Pangea - 'bytes': bytes, - // Pangea# - }; +} + +extension on AudioEncoder { + String get fileExtension { + switch (this) { + case AudioEncoder.aacLc: + case AudioEncoder.aacEld: + case AudioEncoder.aacHe: + return 'm4a'; + case AudioEncoder.opus: + return 'ogg'; + case AudioEncoder.wav: + return 'wav'; + case AudioEncoder.amrNb: + case AudioEncoder.amrWb: + case AudioEncoder.flac: + case AudioEncoder.pcm16bits: + throw UnsupportedError('Not yet used'); + } + } } diff --git a/lib/pages/chat/reply_display.dart b/lib/pages/chat/reply_display.dart index e2bacac83..0b182f719 100644 --- a/lib/pages/chat/reply_display.dart +++ b/lib/pages/chat/reply_display.dart @@ -13,6 +13,8 @@ class ReplyDisplay extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return AnimatedContainer( duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, @@ -21,7 +23,7 @@ class ReplyDisplay extends StatelessWidget { : 0, clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, ), child: Row( children: [ @@ -54,6 +56,7 @@ class _EditContent extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); final event = this.event; if (event == null) { return const SizedBox.shrink(); @@ -62,7 +65,7 @@ class _EditContent extends StatelessWidget { children: [ Icon( Icons.edit, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), Container(width: 15.0), Text( @@ -74,7 +77,7 @@ class _EditContent extends StatelessWidget { overflow: TextOverflow.ellipsis, maxLines: 1, style: TextStyle( - color: Theme.of(context).textTheme.bodyMedium!.color, + color: theme.textTheme.bodyMedium!.color, ), ), ], diff --git a/lib/pages/chat/seen_by_row.dart b/lib/pages/chat/seen_by_row.dart index af8b82069..793a90746 100644 --- a/lib/pages/chat/seen_by_row.dart +++ b/lib/pages/chat/seen_by_row.dart @@ -11,6 +11,8 @@ class SeenByRow extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final seenByUsers = controller.room.getSeenByUsers(controller.timeline!); const maxAvatars = 7; return Container( @@ -48,7 +50,7 @@ class SeenByRow extends StatelessWidget { width: 16, height: 16, child: Material( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, borderRadius: BorderRadius.circular(32), child: Center( child: Text( diff --git a/lib/pages/chat/send_file_dialog.dart b/lib/pages/chat/send_file_dialog.dart index b2885a635..edcb981f3 100644 --- a/lib/pages/chat/send_file_dialog.dart +++ b/lib/pages/chat/send_file_dialog.dart @@ -6,7 +6,7 @@ import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/utils/localized_exception_extension.dart'; +import 'package:fluffychat/utils/error_reporter.dart'; import 'package:fluffychat/utils/size_string.dart'; import '../../utils/resize_image.dart'; @@ -31,6 +31,8 @@ class SendFileDialogState extends State { static const int minSizeToCompress = 20 * 1024; Future _send() async { + final scaffoldMessenger = ScaffoldMessenger.of(context); + final l10n = L10n.of(context)!; for (var file in widget.files) { MatrixImageFile? thumbnail; if (file is MatrixVideoFile && file.bytes.length > minSizeToCompress) { @@ -42,19 +44,24 @@ class SendFileDialogState extends State { }, ); } - final scaffoldMessenger = ScaffoldMessenger.of(context); widget.room .sendFileEvent( file, thumbnail: thumbnail, shrinkImageMaxDimension: origImage ? null : 1600, ) - .catchError((e) { - scaffoldMessenger.showSnackBar( - SnackBar(content: Text((e as Object).toLocalizedString(context))), - ); - return null; - }); + .catchError( + (e, s) { + if (e is FileTooBigMatrixException) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text(l10n.fileIsTooBigForServer)), + ); + return null; + } + ErrorReporter(context, 'Unable to send file').onErrorCallback(e, s); + return null; + }, + ); } Navigator.of(context, rootNavigator: false).pop(); @@ -63,8 +70,10 @@ class SendFileDialogState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + var sendStr = L10n.of(context)!.sendFile; - final bool allFilesAreImages = + final allFilesAreImages = widget.files.every((file) => file is MatrixImageFile); final sizeString = widget.files .fold(0, (p, file) => p + file.bytes.length) @@ -88,9 +97,8 @@ class SendFileDialogState extends State { Flexible( child: Material( borderRadius: BorderRadius.circular(AppConfig.borderRadius), - elevation: - Theme.of(context).appBarTheme.scrolledUnderElevation ?? 4, - shadowColor: Theme.of(context).appBarTheme.shadowColor, + elevation: theme.appBarTheme.scrolledUnderElevation ?? 4, + shadowColor: theme.appBarTheme.shadowColor, clipBehavior: Clip.hardEdge, child: Image.memory( widget.files.first.bytes, diff --git a/lib/pages/chat/sticker_picker_dialog.dart b/lib/pages/chat/sticker_picker_dialog.dart index 39e8fef5d..800c3cd24 100644 --- a/lib/pages/chat/sticker_picker_dialog.dart +++ b/lib/pages/chat/sticker_picker_dialog.dart @@ -25,6 +25,8 @@ class StickerPickerDialogState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final stickerPacks = widget.room.getImagePacks(ImagePackUsage.sticker); final packSlugs = stickerPacks.keys.toList(); @@ -98,7 +100,7 @@ class StickerPickerDialogState extends State { }; return Scaffold( - backgroundColor: Theme.of(context).colorScheme.onInverseSurface, + backgroundColor: theme.colorScheme.onInverseSurface, body: SizedBox( width: double.maxFinite, child: CustomScrollView( diff --git a/lib/pages/chat/typing_indicators.dart b/lib/pages/chat/typing_indicators.dart index 35fbf5d25..a58138a90 100644 --- a/lib/pages/chat/typing_indicators.dart +++ b/lib/pages/chat/typing_indicators.dart @@ -14,6 +14,8 @@ class TypingIndicators extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + const avatarSize = Avatar.defaultSize / 2; return StreamBuilder( @@ -81,7 +83,7 @@ class TypingIndicators extends StatelessWidget { Material( color: // ignore: deprecated_member_use - Theme.of(context).colorScheme.surfaceVariant, + theme.colorScheme.surfaceVariant, borderRadius: const BorderRadius.all( Radius.circular(AppConfig.borderRadius), ), @@ -137,6 +139,7 @@ class __TypingDotsState extends State<_TypingDots> { @override Widget build(BuildContext context) { + final theme = Theme.of(context); const size = 8.0; return Row( @@ -154,7 +157,7 @@ class __TypingDotsState extends State<_TypingDots> { ), decoration: BoxDecoration( borderRadius: BorderRadius.circular(size * 2), - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), ], diff --git a/lib/pages/chat_access_settings/chat_access_settings_controller.dart b/lib/pages/chat_access_settings/chat_access_settings_controller.dart index c0ab1fa7a..fd7624790 100644 --- a/lib/pages/chat_access_settings/chat_access_settings_controller.dart +++ b/lib/pages/chat_access_settings/chat_access_settings_controller.dart @@ -24,6 +24,36 @@ class ChatAccessSettingsController extends State { bool guestAccessLoading = false; Room get room => Matrix.of(context).client.getRoomById(widget.roomId)!; + String get roomVersion => + room + .getState(EventTypes.RoomCreate)! + .content + .tryGet('room_version') ?? + 'Unknown'; + + /// Calculates which join rules are available based on the information on + /// https://spec.matrix.org/v1.11/rooms/#feature-matrix + List get availableJoinRules { + final joinRules = Set.from(JoinRules.values); + + final roomVersionInt = int.tryParse(roomVersion); + + // Knock is only supported for rooms up from version 7: + if (roomVersionInt != null && roomVersionInt <= 6) { + joinRules.remove(JoinRules.knock); + } + + // Not yet supported in FluffyChat: + joinRules.remove(JoinRules.restricted); + joinRules.remove(JoinRules.knockRestricted); + + // If an unsupported join rule is the current join rule, display it: + final currentJoinRule = room.joinRules; + if (currentJoinRule != null) joinRules.add(currentJoinRule); + + return joinRules.toList(); + } + void setJoinRule(JoinRules? newJoinRules) async { if (newJoinRules == null) return; setState(() { diff --git a/lib/pages/chat_access_settings/chat_access_settings_page.dart b/lib/pages/chat_access_settings/chat_access_settings_page.dart index 7de6f3793..a4a6538a6 100644 --- a/lib/pages/chat_access_settings/chat_access_settings_page.dart +++ b/lib/pages/chat_access_settings/chat_access_settings_page.dart @@ -14,6 +14,8 @@ class ChatAccessSettingsPageView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final room = controller.room; return Scaffold( appBar: AppBar( @@ -38,7 +40,7 @@ class ChatAccessSettingsPageView extends StatelessWidget { title: Text( L10n.of(context)!.visibilityOfTheChatHistory, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -56,17 +58,17 @@ class ChatAccessSettingsPageView extends StatelessWidget { ? null : controller.setHistoryVisibility, ), - Divider(color: Theme.of(context).dividerColor), + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context)!.whoIsAllowedToJoinThisGroup, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), ), - for (final joinRule in JoinRules.values) + for (final joinRule in controller.availableJoinRules) if (joinRule != JoinRules.private) RadioListTile.adaptive( title: Text( @@ -79,14 +81,14 @@ class ChatAccessSettingsPageView extends StatelessWidget { ? null : controller.setJoinRule, ), - Divider(color: Theme.of(context).dividerColor), + Divider(color: theme.dividerColor), if ({JoinRules.public, JoinRules.knock} .contains(room.joinRules)) ...[ ListTile( title: Text( L10n.of(context)!.areGuestsAllowedToJoin, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -105,12 +107,12 @@ class ChatAccessSettingsPageView extends StatelessWidget { ? null : controller.setGuestAccess, ), - Divider(color: Theme.of(context).dividerColor), + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context)!.publicChatAddresses, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -163,7 +165,7 @@ class ChatAccessSettingsPageView extends StatelessWidget { ); }, ), - Divider(color: Theme.of(context).dividerColor), + Divider(color: theme.dividerColor), FutureBuilder( future: room.client.getRoomVisibilityOnDirectory(room.id), builder: (context, snapshot) => SwitchListTile.adaptive( @@ -225,6 +227,8 @@ class _AliasListTile extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return ListTile( leading: isCanonicalAlias ? const Icon(Icons.star) @@ -238,15 +242,15 @@ class _AliasListTile extends StatelessWidget { 'https://matrix.to/#/$alias', style: TextStyle( decoration: TextDecoration.underline, - decorationColor: Theme.of(context).colorScheme.primary, - color: Theme.of(context).colorScheme.primary, + decorationColor: theme.colorScheme.primary, + color: theme.colorScheme.primary, fontSize: 14, ), ), ), trailing: onDelete != null ? IconButton( - color: Theme.of(context).colorScheme.error, + color: theme.colorScheme.error, icon: const Icon(Icons.delete_outlined), onPressed: onDelete, ) diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index 0afa56086..5c5d1b840 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -31,6 +31,8 @@ class ChatDetailsView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final room = Matrix.of(context).client.getRoomById(controller.roomId!); // #Pangea if (room == null || room.membership == Membership.leave) { @@ -56,37 +58,26 @@ class ChatDetailsView extends StatelessWidget { final actualMembersCount = (room.summary.mInvitedMemberCount ?? 0) + (room.summary.mJoinedMemberCount ?? 0); final canRequestMoreMembers = members.length < actualMembersCount; - final iconColor = Theme.of(context).textTheme.bodyLarge!.color; + final iconColor = theme.textTheme.bodyLarge!.color; final displayname = room.getLocalizedDisplayname( MatrixLocals(L10n.of(context)!), ); return Scaffold( appBar: AppBar( - leading: - // #Pangea - !room.isSpace - ? - // Pangea# - controller.widget.embeddedCloseButton ?? - const Center(child: BackButton()) - // #Pangea - : BackButton( - onPressed: () => context.go("/rooms"), - ) - // Pangea# - , - elevation: Theme.of(context).appBarTheme.elevation, + leading: controller.widget.embeddedCloseButton ?? + const Center(child: BackButton()), + elevation: theme.appBarTheme.elevation, actions: [ // #Pangea // if (room.canonicalAlias.isNotEmpty) - // IconButton( - // tooltip: L10n.of(context)!.share, - // icon: Icon(Icons.adaptive.share_outlined), - // onPressed: () => FluffyShare.share( - // AppConfig.inviteLinkPrefix + room.canonicalAlias, - // context, + // IconButton( + // tooltip: L10n.of(context)!.share, + // icon: Icon(Icons.adaptive.share_outlined), + // onPressed: () => FluffyShare.share( + // AppConfig.inviteLinkPrefix + room.canonicalAlias, + // context, + // ), // ), - // ), // Pangea# if (controller.widget.embeddedCloseButton == null) ChatSettingsPopupMenu(room, false), @@ -98,7 +89,7 @@ class ChatDetailsView extends StatelessWidget { ), // title: Text(L10n.of(context)!.chatDetails), // Pangea# - backgroundColor: Theme.of(context).appBarTheme.backgroundColor, + backgroundColor: theme.appBarTheme.backgroundColor, ), body: MaxWidthBody( // #Pangea @@ -122,32 +113,12 @@ class ChatDetailsView extends StatelessWidget { padding: const EdgeInsets.all(32.0), child: Stack( children: [ - Material( - elevation: Theme.of(context) - .appBarTheme - .scrolledUnderElevation ?? - 4, - shadowColor: Theme.of(context) - .appBarTheme - .shadowColor, - shape: RoundedRectangleBorder( - side: BorderSide( - color: Theme.of(context).dividerColor, - ), - borderRadius: BorderRadius.circular( - Avatar.defaultSize * 2.5, - ), - ), - // #Pangea - // Hero animation is causing weird visual glitch - // Probably not worth keeping - // child: Hero( - // tag: controller.widget - // .embeddedCloseButton != - // null - // ? 'embedded_content_banner' - // : 'content_banner', - // Pangea# + Hero( + tag: controller + .widget.embeddedCloseButton != + null + ? 'embedded_content_banner' + : 'content_banner', child: Avatar( mxContent: room.avatar, name: displayname, @@ -201,9 +172,8 @@ class ChatDetailsView extends StatelessWidget { size: 16, ), style: TextButton.styleFrom( - foregroundColor: Theme.of(context) - .colorScheme - .onSurface, + foregroundColor: + theme.colorScheme.onSurface, ), label: Text( room.isDirectChat @@ -211,7 +181,7 @@ class ChatDetailsView extends StatelessWidget { : displayname, maxLines: 1, overflow: TextOverflow.ellipsis, - // style: const TextStyle(fontSize: 18), + style: const TextStyle(fontSize: 18), ), ), TextButton.icon( @@ -225,9 +195,8 @@ class ChatDetailsView extends StatelessWidget { size: 14, ), style: TextButton.styleFrom( - foregroundColor: Theme.of(context) - .colorScheme - .secondary, + foregroundColor: + theme.colorScheme.secondary, ), label: Text( L10n.of(context)!.countParticipants( @@ -243,13 +212,9 @@ class ChatDetailsView extends StatelessWidget { ), ], ), - Divider( - height: 1, - color: Theme.of(context).dividerColor, - ), - // if (room.canSendEvent('m.room.name')) + Divider(color: theme.dividerColor), + // #Pangea if (room.isRoomAdmin) - // #Pangea ClassNameButton( room: room, controller: controller, @@ -259,32 +224,16 @@ class ChatDetailsView extends StatelessWidget { room: room, controller: controller, ), - // #Pangea RoomCapacityButton( room: room, controller: controller, ), - // Pangea# - // commenting out language settings in spaces for now - // if (room.languageSettings != null && room.isRoomAdmin) - // LanguageSettings( - // roomId: controller.roomId, - // startOpen: false, - // ), - - // Commenting out pangea room rules for now - // if (room.pangeaRoomRules != null) - // RoomRulesEditor( - // roomId: controller.roomId, - // startOpen: false, - // ), - // if (!room.canChangeStateEvent(EventTypes.RoomTopic)) // ListTile( // title: Text( // L10n.of(context)!.chatDescription, // style: TextStyle( - // color: Theme.of(context).colorScheme.secondary, + // color: theme.colorScheme.secondary, // fontWeight: FontWeight.bold, // ), // ), @@ -294,15 +243,14 @@ class ChatDetailsView extends StatelessWidget { // padding: const EdgeInsets.all(16.0), // child: TextButton.icon( // onPressed: controller.setTopicAction, - // label: Text(L10n.of(context)!.setChatDescription), + // label: + // Text(L10n.of(context)!.setChatDescription), // icon: const Icon(Icons.edit_outlined), // style: TextButton.styleFrom( - // backgroundColor: Theme.of(context) - // .colorScheme - // .secondaryContainer, - // foregroundColor: Theme.of(context) - // .colorScheme - // .onSecondaryContainer, + // backgroundColor: + // theme.colorScheme.secondaryContainer, + // foregroundColor: + // theme.colorScheme.onSecondaryContainer, // ), // ), // ), @@ -324,24 +272,19 @@ class ChatDetailsView extends StatelessWidget { // fontStyle: room.topic.isEmpty // ? FontStyle.italic // : FontStyle.normal, - // color: - // Theme.of(context).textTheme.bodyMedium!.color, + // color: theme.textTheme.bodyMedium!.color, // decorationColor: - // Theme.of(context).textTheme.bodyMedium!.color, + // theme.textTheme.bodyMedium!.color, // ), // onOpen: (url) => // UrlLauncher(context, url.url).launchUrl(), // ), // ), // const SizedBox(height: 16), - // Divider( - // height: 1, - // color: Theme.of(context).dividerColor, - // ), + // Divider(color: theme.dividerColor), // ListTile( // leading: CircleAvatar( - // backgroundColor: - // Theme.of(context).scaffoldBackgroundColor, + // backgroundColor: theme.scaffoldBackgroundColor, // foregroundColor: iconColor, // child: const Icon( // Icons.insert_emoticon_outlined, @@ -354,23 +297,24 @@ class ChatDetailsView extends StatelessWidget { // trailing: const Icon(Icons.chevron_right_outlined), // ), // if (!room.isDirectChat) - // ListTile( - // leading: CircleAvatar( - // backgroundColor: - // Theme.of(context).scaffoldBackgroundColor, - // foregroundColor: iconColor, - // child: const Icon(Icons.shield_outlined), + // ListTile( + // leading: CircleAvatar( + // backgroundColor: theme.scaffoldBackgroundColor, + // foregroundColor: iconColor, + // child: const Icon(Icons.shield_outlined), + // ), + // title: Text( + // L10n.of(context)!.accessAndVisibility, + // ), + // subtitle: Text( + // L10n.of(context)! + // .accessAndVisibilityDescription, + // ), + // onTap: () => context + // .push('/rooms/${room.id}/details/access'), + // trailing: + // const Icon(Icons.chevron_right_outlined), // ), - // title: Text( - // L10n.of(context)!.accessAndVisibility, - // ), - // subtitle: Text( - // L10n.of(context)!.accessAndVisibilityDescription, - // ), - // onTap: () => context - // .push('/rooms/${room.id}/details/access'), - // trailing: const Icon(Icons.chevron_right_outlined), - // ), // if (!room.isDirectChat) if (!room.isDirectChat && !room.isSpace && @@ -382,8 +326,7 @@ class ChatDetailsView extends StatelessWidget { title: Text( L10n.of(context)!.editChatPermissions, style: TextStyle( - color: - Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -392,24 +335,19 @@ class ChatDetailsView extends StatelessWidget { L10n.of(context)!.whoCanPerformWhichAction, ), leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, + backgroundColor: theme.scaffoldBackgroundColor, foregroundColor: iconColor, child: const Icon( Icons.edit_attributes_outlined, ), ), - // #Pangea - // trailing: const Icon(Icons.chevron_right_outlined), - // Pangea# + trailing: + const Icon(Icons.chevron_right_outlined), onTap: () => context.push( '/rooms/${room.id}/details/permissions', ), ), - Divider( - height: 1, - color: Theme.of(context).dividerColor, - ), + Divider(color: theme.dividerColor), // #Pangea if (room.canInvite && !room.isDirectChat && @@ -486,8 +424,8 @@ class ChatDetailsView extends StatelessWidget { ), ), onTap: () async { - OkCancelResult confirmed = OkCancelResult.ok; - bool shouldGo = false; + var confirmed = OkCancelResult.ok; + var shouldGo = false; // archiveSpace has its own popup; only show if not space if (!room.isSpace) { confirmed = await showOkCancelAlertDialog( @@ -539,10 +477,10 @@ class ChatDetailsView extends StatelessWidget { ), ), onTap: () async { - OkCancelResult confirmed = OkCancelResult.ok; - bool shouldGo = false; + var confirmed = OkCancelResult.ok; + var shouldGo = false; // If user is only admin, room will be archived - final bool onlyAdmin = await room.isOnlyAdmin(); + final onlyAdmin = await room.isOnlyAdmin(); // archiveSpace has its own popup; only show if not space if (!room.isSpace) { confirmed = await showOkCancelAlertDialog( @@ -630,7 +568,7 @@ class ChatDetailsView extends StatelessWidget { actualMembersCount.toString(), ), style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -640,17 +578,17 @@ class ChatDetailsView extends StatelessWidget { // ListTile( // title: Text(L10n.of(context)!.inviteContact), // leading: CircleAvatar( - // backgroundColor: Theme.of(context) - // .colorScheme - // .primaryContainer, - // foregroundColor: Theme.of(context) - // .colorScheme - // .onPrimaryContainer, + // backgroundColor: + // theme.colorScheme.primaryContainer, + // foregroundColor: + // theme.colorScheme.onPrimaryContainer, // radius: Avatar.defaultSize / 2, // child: const Icon(Icons.add_outlined), // ), - // trailing: const Icon(Icons.chevron_right_outlined), - // onTap: () => context.go('/rooms/${room.id}/invite'), + // trailing: + // const Icon(Icons.chevron_right_outlined), + // onTap: () => + // context.go('/rooms/${room.id}/invite'), // ), // Pangea# ], @@ -665,8 +603,7 @@ class ChatDetailsView extends StatelessWidget { ), ), leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, + backgroundColor: theme.scaffoldBackgroundColor, child: const Icon( Icons.group_outlined, color: Colors.grey, diff --git a/lib/pages/chat_details/participant_list_item.dart b/lib/pages/chat_details/participant_list_item.dart index 9b5580692..dc24163d5 100644 --- a/lib/pages/chat_details/participant_list_item.dart +++ b/lib/pages/chat_details/participant_list_item.dart @@ -13,6 +13,8 @@ class ParticipantListItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final membershipBatch = switch (user.membership) { Membership.ban => L10n.of(context)!.banned, Membership.invite => L10n.of(context)!.invited, @@ -54,11 +56,13 @@ class ParticipantListItem extends StatelessWidget { margin: const EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration( // #Pangea - // color: Theme.of(context).colorScheme.primaryContainer, - color: Theme.of(context).secondaryHeaderColor, + // color: theme.colorScheme.primaryContainer, + color: theme.secondaryHeaderColor, + // Pangea# borderRadius: BorderRadius.circular(8), + // #Pangea // border: Border.all( - // color: Theme.of(context).colorScheme.primary, + // color: theme.colorScheme.primary, // ), // Pangea# ), @@ -67,7 +71,7 @@ class ParticipantListItem extends StatelessWidget { // #Pangea // style: TextStyle( // fontSize: 14, - // color: Theme.of(context).colorScheme.primary, + // color: theme.colorScheme.primary, // ), // Pangea# ), @@ -78,7 +82,7 @@ class ParticipantListItem extends StatelessWidget { padding: const EdgeInsets.all(4), margin: const EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration( - color: Theme.of(context).secondaryHeaderColor, + color: theme.secondaryHeaderColor, borderRadius: BorderRadius.circular(8), ), child: Center(child: Text(membershipBatch)), diff --git a/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart b/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart index d53239a07..13974dfca 100644 --- a/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart +++ b/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart @@ -1,14 +1,12 @@ -import 'package:flutter/material.dart'; - -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; -import 'package:matrix/matrix.dart'; -import 'package:url_launcher/url_launcher_string.dart'; - import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart'; import 'package:fluffychat/utils/beautify_string_extension.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart'; +import 'package:url_launcher/url_launcher_string.dart'; class ChatEncryptionSettingsView extends StatelessWidget { final ChatEncryptionSettingsController controller; @@ -17,6 +15,8 @@ class ChatEncryptionSettingsView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final room = controller.room; return StreamBuilder( stream: room.client.onSync.stream.where( @@ -42,10 +42,8 @@ class ChatEncryptionSettingsView extends StatelessWidget { children: [ SwitchListTile( secondary: CircleAvatar( - foregroundColor: - Theme.of(context).colorScheme.onPrimaryContainer, - backgroundColor: - Theme.of(context).colorScheme.primaryContainer, + foregroundColor: theme.colorScheme.onPrimaryContainer, + backgroundColor: theme.colorScheme.primaryContainer, child: const Icon(Icons.lock_outlined), ), title: Text(L10n.of(context)!.encryptThisChat), @@ -56,7 +54,7 @@ class ChatEncryptionSettingsView extends StatelessWidget { // Icon( // CupertinoIcons.lock_shield, // size: 128, - // color: Theme.of(context).colorScheme.onInverseSurface, + // color: theme.colorScheme.onInverseSurface, // ), // Pangea# const Divider(), @@ -145,13 +143,10 @@ class ChatEncryptionSettingsView extends StatelessWidget { AppConfig.borderRadius, ), side: BorderSide( - color: - Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), - color: Theme.of(context) - .colorScheme - .primaryContainer, + color: theme.colorScheme.primaryContainer, child: Padding( padding: const EdgeInsets.all(4.0), child: Text( @@ -159,9 +154,7 @@ class ChatEncryptionSettingsView extends StatelessWidget { maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( - color: Theme.of(context) - .colorScheme - .primary, + color: theme.colorScheme.primary, fontSize: 12, fontStyle: FontStyle.italic, ), @@ -176,7 +169,7 @@ class ChatEncryptionSettingsView extends StatelessWidget { L10n.of(context)!.unknownEncryptionAlgorithm, style: TextStyle( fontFamily: 'RobotoMono', - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), ), diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index ec34a5b81..2d1302993 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/pages/chat/send_file_dialog.dart'; import 'package:fluffychat/pages/chat_list/chat_list_view.dart'; import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; @@ -14,9 +15,12 @@ import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/firebase_analytics.dart'; import 'package:fluffychat/pangea/widgets/subscription/subscription_snackbar.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; +import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:fluffychat/utils/show_update_snackbar.dart'; import 'package:fluffychat/utils/tor_stub.dart' if (dart.library.html) 'package:tor_detector_web/tor_detector_web.dart'; +import 'package:fluffychat/widgets/avatar.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -24,6 +28,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_shortcuts/flutter_shortcuts.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:uni_links/uni_links.dart'; @@ -39,7 +44,6 @@ import '../../widgets/matrix.dart'; enum SelectMode { normal, share, - select, } enum PopupMenuAction { @@ -53,20 +57,38 @@ enum PopupMenuAction { enum ActiveFilter { allChats, - groups, messages, + groups, + unread, spaces, } +extension LocalizedActiveFilter on ActiveFilter { + String toLocalizedString(BuildContext context) { + switch (this) { + case ActiveFilter.allChats: + return L10n.of(context)!.all; + case ActiveFilter.messages: + return L10n.of(context)!.messages; + case ActiveFilter.unread: + return L10n.of(context)!.unread; + case ActiveFilter.groups: + return L10n.of(context)!.groups; + case ActiveFilter.spaces: + return L10n.of(context)!.spaces; + } + } +} + class ChatList extends StatefulWidget { static BuildContext? contextForVoip; - final bool displayNavigationRail; final String? activeChat; + final bool displayNavigationRail; const ChatList({ super.key, - this.displayNavigationRail = false, required this.activeChat, + this.displayNavigationRail = false, }); @override @@ -81,116 +103,167 @@ class ChatListController extends State StreamSubscription? _intentUriStreamSubscription; - bool get displayNavigationBar => - !FluffyThemes.isColumnMode(context) && - (spaces.isNotEmpty || AppConfig.separateChatTypes); - - String? activeSpaceId; - - void resetActiveSpaceId() { - setState(() { - selectedRoomIds.clear(); - activeSpaceId = null; - //#Pangea - context.go("/rooms"); - //Pangea# - }); - } - - void setActiveSpace(String? spaceId) { - setState(() { - selectedRoomIds.clear(); - activeSpaceId = spaceId; - activeFilter = ActiveFilter.spaces; - // #Pangea - // don't show all spaces view if in column mode - if (spaceId == null && FluffyThemes.isColumnMode(context)) { - activeFilter = ActiveFilter.allChats; - } - // Pangea# - }); - } - - void createNewSpace() async { - final spaceId = await context.push('/rooms/newspace'); - if (spaceId != null) { - setActiveSpace(spaceId); - } - } - - int get selectedIndex { - switch (activeFilter) { - case ActiveFilter.allChats: - case ActiveFilter.messages: - return 0; - case ActiveFilter.groups: - return 1; - case ActiveFilter.spaces: - return AppConfig.separateChatTypes ? 2 : 1; - } - } - - // #Pangea - bool isSelected(int i) { - if (activeFilter == ActiveFilter.spaces && activeSpaceId != null) { - return false; - } - return i == selectedIndex; - } - // Pangea# - - ActiveFilter getActiveFilterByDestination(int? i) { - switch (i) { - case 1: - if (AppConfig.separateChatTypes) { - return ActiveFilter.groups; - } - return ActiveFilter.spaces; - case 2: - return ActiveFilter.spaces; - case 0: - default: - if (AppConfig.separateChatTypes) { - return ActiveFilter.messages; - } - return ActiveFilter.allChats; - } - } - - void onDestinationSelected(int? i) { - setState(() { - // #Pangea - debugPrint('onDestinationSelected $i'); - // Pangea# - selectedRoomIds.clear(); - activeFilter = getActiveFilterByDestination(i); - // #Pangea - if (activeFilter != ActiveFilter.spaces) { - activeSpaceId = null; - } - // Pangea# - }); - // #Pangea - final bool clickedAllSpaces = (!AppConfig.separateChatTypes && i == 1) || - (AppConfig.separateChatTypes && i == 2); - if (clickedAllSpaces) { - setActiveSpace(null); - } - // Pangea# + void createNewSpace() { + context.push('/rooms/newspace'); } ActiveFilter activeFilter = AppConfig.separateChatTypes ? ActiveFilter.messages : ActiveFilter.allChats; + String? _activeSpaceId; + String? get activeSpaceId => _activeSpaceId; + + void setActiveSpace(String spaceId) async { + await Matrix.of(context).client.getRoomById(spaceId)!.postLoad(); + + setState(() { + _activeSpaceId = spaceId; + }); + + // #Pangea + if (FluffyThemes.isColumnMode(context)) { + context.go('/rooms/$spaceId/details'); + } + // Pangea# + } + + void clearActiveSpace() => setState(() { + _activeSpaceId = null; + }); + + void onChatTap(Room room) async { + if (room.membership == Membership.invite) { + final inviterId = + room.getState(EventTypes.RoomMember, room.client.userID!)?.senderId; + final inviteAction = await showModalActionSheet( + context: context, + message: room.isDirectChat + // #Pangea + ? L10n.of(context)!.invitePrivateChat + // : L10n.of(context)!.inviteGroupChat, + : L10n.of(context)!.inviteChat, + // Pangea# + title: room.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), + actions: [ + SheetAction( + key: InviteActions.accept, + label: L10n.of(context)!.accept, + icon: Icons.check_outlined, + isDefaultAction: true, + ), + SheetAction( + key: InviteActions.decline, + label: L10n.of(context)!.decline, + icon: Icons.close_outlined, + isDestructiveAction: true, + ), + SheetAction( + key: InviteActions.block, + label: L10n.of(context)!.block, + icon: Icons.block_outlined, + isDestructiveAction: true, + ), + ], + ); + if (inviteAction == null) return; + if (inviteAction == InviteActions.block) { + context.go('/rooms/settings/security/ignorelist', extra: inviterId); + return; + } + if (inviteAction == InviteActions.decline) { + await showFutureLoadingDialog( + context: context, + future: room.leave, + ); + return; + } + final joinResult = await showFutureLoadingDialog( + context: context, + future: () async { + final waitForRoom = room.client.waitForRoomInSync( + room.id, + join: true, + ); + await room.join(); + await waitForRoom; + }, + ); + if (joinResult.error != null) return; + } + + if (room.membership == Membership.ban) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(L10n.of(context)!.youHaveBeenBannedFromThisChat), + ), + ); + return; + } + + if (room.membership == Membership.leave) { + context.go('/rooms/archive/${room.id}'); + return; + } + + if (room.isSpace) { + setActiveSpace(room.id); + return; + } + // Share content into this room + final shareContent = Matrix.of(context).shareContent; + if (shareContent != null) { + final shareFile = shareContent.tryGet('file'); + if (shareContent.tryGet('msgtype') == 'chat.fluffy.shared_file' && + shareFile != null) { + await showDialog( + context: context, + useRootNavigator: false, + builder: (c) => SendFileDialog( + files: [shareFile], + room: room, + ), + ); + Matrix.of(context).shareContent = null; + } else { + final consent = await showOkCancelAlertDialog( + context: context, + title: L10n.of(context)!.forward, + message: L10n.of(context)!.forwardMessageTo( + room.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), + ), + okLabel: L10n.of(context)!.forward, + cancelLabel: L10n.of(context)!.cancel, + ); + if (consent == OkCancelResult.cancel) { + Matrix.of(context).shareContent = null; + return; + } + if (consent == OkCancelResult.ok) { + room.sendEvent(shareContent); + Matrix.of(context).shareContent = null; + } + } + } + + context.go('/rooms/${room.id}'); + } + bool Function(Room) getRoomFilterByActiveFilter(ActiveFilter activeFilter) { switch (activeFilter) { case ActiveFilter.allChats: + // #Pangea + // return (room) => true; + return (room) => !room.isAnalyticsRoom; + // Pangea# + case ActiveFilter.messages: return (room) => - !room.isSpace // #Pangea + !room.isSpace && + room.isDirectChat + // #Pangea && !room.isAnalyticsRoom; - // Pangea#; + // Pangea# case ActiveFilter.groups: return (room) => !room.isSpace && @@ -198,24 +271,21 @@ class ChatListController extends State && !room.isAnalyticsRoom; // Pangea#; - case ActiveFilter.messages: + case ActiveFilter.unread: return (room) => - !room.isSpace && - room.isDirectChat // #Pangea + room.isUnreadOrInvited // #Pangea && !room.isAnalyticsRoom; // Pangea#; case ActiveFilter.spaces: - return (r) => r.isSpace; + return (room) => room.isSpace; } } List get filteredRooms => Matrix.of(context) .client .rooms - .where( - getRoomFilterByActiveFilter(activeFilter), - ) + .where(getRoomFilterByActiveFilter(activeFilter)) .toList(); bool isSearchMode = false; @@ -227,9 +297,6 @@ class ChatListController extends State bool isSearching = false; static const String _serverStoreNamespace = 'im.fluffychat.search.server'; - //#Pangea - final PangeaController pangeaController = MatrixState.pangeaController; - //Pangea# void setServer() async { final newServer = await showTextInputDialog( @@ -387,15 +454,11 @@ class ChatListController extends State List get spaces => Matrix.of(context).client.rooms.where((r) => r.isSpace).toList(); - final selectedRoomIds = {}; - String? get activeChat => widget.activeChat; SelectMode get selectMode => Matrix.of(context).shareContent != null ? SelectMode.share - : selectedRoomIds.isEmpty - ? SelectMode.normal - : SelectMode.select; + : SelectMode.normal; void _processIncomingSharedFiles(List files) { if (files.isEmpty) return; @@ -444,15 +507,12 @@ class ChatListController extends State // For sharing images coming from outside the app while the app is closed ReceiveSharingIntent.getInitialMedia().then(_processIncomingSharedFiles); - // #Pangea - // dependency is outdated and prevents app from building - // // For sharing or opening urls/text coming from outside the app while the app is in the memory - // _intentDataStreamSubscription = ReceiveSharingIntent.getTextStream() - // .listen(_processIncomingSharedText, onError: print); + // For sharing or opening urls/text coming from outside the app while the app is in the memory + _intentDataStreamSubscription = ReceiveSharingIntent.getTextStream() + .listen(_processIncomingSharedText, onError: print); - // // For sharing or opening urls/text coming from outside the app while the app is closed - // ReceiveSharingIntent.getInitialText().then(_processIncomingSharedText); - // Pangea# + // For sharing or opening urls/text coming from outside the app while the app is closed + ReceiveSharingIntent.getInitialText().then(_processIncomingSharedText); // For receiving shared Uris _intentUriStreamSubscription = linkStream.listen(_processIncomingUris); @@ -493,6 +553,7 @@ class ChatListController extends State searchServer = Matrix.of(context).store.getString(_serverStoreNamespace); Matrix.of(context).backgroundPush?.setupPush(); + UpdateNotifier.showUpdateSnackBar(context); } // Workaround for system UI overlay style not applied on app start @@ -504,8 +565,8 @@ class ChatListController extends State _checkTorBrowser(); //#Pangea - classStream = pangeaController.classController.stateStream.listen((event) { - // if (event["activeSpaceId"] != null && mounted) { + classStream = MatrixState.pangeaController.classController.stateStream + .listen((event) { if (mounted) { setActiveSpace(event["activeSpaceId"]); if (event["activeSpaceId"] != null) { @@ -514,26 +575,27 @@ class ChatListController extends State } }); - _invitedSpaceSubscription = pangeaController - .matrixState.client.onSync.stream + _invitedSpaceSubscription = MatrixState + .pangeaController.matrixState.client.onSync.stream .where((event) => event.rooms?.invite != null) .listen((event) async { for (final inviteEntry in event.rooms!.invite!.entries) { if (inviteEntry.value.inviteState == null) continue; - final bool isSpace = inviteEntry.value.inviteState!.any( + final isSpace = inviteEntry.value.inviteState!.any( (event) => event.type == EventTypes.RoomCreate && event.content['type'] == 'm.space', ); - final bool isAnalytics = inviteEntry.value.inviteState!.any( + final isAnalytics = inviteEntry.value.inviteState!.any( (event) => event.type == EventTypes.RoomCreate && event.content['type'] == PangeaRoomTypes.analytics, ); if (isSpace) { - final String spaceId = inviteEntry.key; - final Room? space = pangeaController.matrixState.client.getRoomById( + final spaceId = inviteEntry.key; + final space = + MatrixState.pangeaController.matrixState.client.getRoomById( spaceId, ); if (space != null) { @@ -546,8 +608,8 @@ class ChatListController extends State } if (isAnalytics) { - final Room? analyticsRoom = - pangeaController.matrixState.client.getRoomById(inviteEntry.key); + final analyticsRoom = MatrixState.pangeaController.matrixState.client + .getRoomById(inviteEntry.key); try { await analyticsRoom?.join(); } catch (err, s) { @@ -562,8 +624,8 @@ class ChatListController extends State } }); - _subscriptionStatusStream ??= pangeaController - .subscriptionController.subscriptionStream.stream + _subscriptionStatusStream ??= MatrixState + .pangeaController.subscriptionController.subscriptionStream.stream .listen((event) { if (mounted) { showSubscribedSnackbar(context); @@ -573,7 +635,7 @@ class ChatListController extends State // listen for space child updates for any space that is not the active space // so that when the user navigates to the space that was updated, it will // reload any rooms that have been added / removed - final client = pangeaController.matrixState.client; + final client = MatrixState.pangeaController.matrixState.client; _spaceChildSubscription ??= client.onRoomState.stream.where((u) { return u.state.type == EventTypes.SpaceChild && u.roomId != activeSpaceId; }).listen((update) { @@ -599,129 +661,286 @@ class ChatListController extends State super.dispose(); } - // #Pangea - final StreamController selectionsStream = - StreamController.broadcast(); - // Pangea# - - void toggleSelection(String roomId) { - // #Pangea - // setState( - // () => selectedRoomIds.contains(roomId) - // ? selectedRoomIds.remove(roomId) - // : selectedRoomIds.add(roomId), - // ); - selectedRoomIds.contains(roomId) - ? selectedRoomIds.remove(roomId) - : selectedRoomIds.add(roomId); - selectionsStream.add(roomId); - // Pangea# - } - - Future toggleUnread() async { - await showFutureLoadingDialog( - context: context, - future: () async { - final markUnread = anySelectedRoomNotMarkedUnread; - final client = Matrix.of(context).client; - for (final roomId in selectedRoomIds) { - final room = client.getRoomById(roomId)!; - if (room.markedUnread == markUnread) continue; - await client.getRoomById(roomId)!.markUnread(markUnread); - } - }, - ); - cancelAction(); - } - - Future toggleFavouriteRoom() async { - await showFutureLoadingDialog( - context: context, - future: () async { - final makeFavorite = anySelectedRoomNotFavorite; - final client = Matrix.of(context).client; - for (final roomId in selectedRoomIds) { - final room = client.getRoomById(roomId)!; - if (room.isFavourite == makeFavorite) continue; - await client.getRoomById(roomId)!.setFavourite(makeFavorite); - } - }, - ); - cancelAction(); - } - - Future toggleMuted() async { - await showFutureLoadingDialog( - context: context, - future: () async { - final newState = anySelectedRoomNotMuted - ? PushRuleState.mentionsOnly - : PushRuleState.notify; - final client = Matrix.of(context).client; - for (final roomId in selectedRoomIds) { - final room = client.getRoomById(roomId)!; - if (room.pushRuleState == newState) continue; - await client.getRoomById(roomId)!.setPushRuleState(newState); - } - }, - ); - cancelAction(); - } - - Future archiveAction() async { - final confirmed = await showOkCancelAlertDialog( - useRootNavigator: false, - context: context, - title: L10n.of(context)!.areYouSure, - okLabel: L10n.of(context)!.yes, - cancelLabel: L10n.of(context)!.cancel, - message: L10n.of(context)!.archiveRoomDescription, - ) == - OkCancelResult.ok; - if (!confirmed) return; - // #Pangea - final bool archivedActiveRoom = - selectedRoomIds.contains(Matrix.of(context).activeRoomId); - // Pangea# - await showFutureLoadingDialog( - context: context, - future: () => _archiveSelectedRooms(), - ); - // #Pangea - // setState(() {}); - if (archivedActiveRoom) { - context.go('/rooms'); + void chatContextAction( + Room room, + BuildContext posContext, [ + Room? space, + ]) async { + if (room.membership == Membership.invite) { + return onChatTap(room); } - // Pangea# - } - // #Pangea - Future leaveAction() async { - final bool onlyAdmin = await Matrix.of(context) - .client - .getRoomById(selectedRoomIds.first) - ?.isOnlyAdmin() ?? - false; - final confirmed = await showOkCancelAlertDialog( + final overlay = + Overlay.of(posContext).context.findRenderObject() as RenderBox; + + final button = posContext.findRenderObject() as RenderBox; + + final position = RelativeRect.fromRect( + Rect.fromPoints( + button.localToGlobal(const Offset(0, -65), ancestor: overlay), + button.localToGlobal( + button.size.bottomRight(Offset.zero) + const Offset(-50, 0), + ancestor: overlay, + ), + ), + Offset.zero & overlay.size, + ); + + final displayname = + room.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)); + + final spacesWithPowerLevels = room.client.rooms + .where( + (space) => + space.isSpace && + space.canChangeStateEvent(EventTypes.SpaceChild) && + !space.spaceChildren.any((c) => c.roomId == room.id), + ) + .toList(); + + final action = await showMenu( + context: posContext, + position: position, + items: [ + PopupMenuItem( + value: ChatContextAction.open, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Avatar( + mxContent: room.avatar, + size: Avatar.defaultSize / 2, + name: displayname, + ), + const SizedBox(width: 12), + Text( + displayname, + style: + TextStyle(color: Theme.of(context).colorScheme.onSurface), + ), + ], + ), + ), + const PopupMenuDivider(), + if (space != null) + PopupMenuItem( + value: ChatContextAction.goToSpace, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Avatar( + mxContent: space.avatar, + size: Avatar.defaultSize / 2, + name: space.getLocalizedDisplayname(), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + L10n.of(context)! + .goToSpace(space.getLocalizedDisplayname()), + ), + ), + ], + ), + ), + PopupMenuItem( + value: ChatContextAction.mute, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + room.pushRuleState == PushRuleState.notify + ? Icons.notifications_off_outlined + : Icons.notifications_off, + ), + const SizedBox(width: 12), + Text( + room.pushRuleState == PushRuleState.notify + ? L10n.of(context)!.muteChat + : L10n.of(context)!.unmuteChat, + ), + ], + ), + ), + PopupMenuItem( + value: ChatContextAction.markUnread, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + room.markedUnread + ? Icons.mark_as_unread + : Icons.mark_as_unread_outlined, + ), + const SizedBox(width: 12), + Text( + room.markedUnread + ? L10n.of(context)!.markAsRead + : L10n.of(context)!.markAsUnread, + ), + ], + ), + ), + PopupMenuItem( + value: ChatContextAction.favorite, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(room.isFavourite ? Icons.push_pin : Icons.push_pin_outlined), + const SizedBox(width: 12), + Text( + room.isFavourite + ? L10n.of(context)!.unpin + : L10n.of(context)!.pin, + ), + ], + ), + ), + if (spacesWithPowerLevels.isNotEmpty) + PopupMenuItem( + value: ChatContextAction.addToSpace, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.group_work_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.addToSpace), + ], + ), + ), + // #Pangea + // if the room has a parent for which the user has a high enough power level + // to set parent's space child events, show option to remove the room from the space + if (room.spaceParents.isNotEmpty && + room.pangeaSpaceParents.any( + (r) => r.canChangeStateEvent(EventTypes.SpaceChild), + ) && + activeSpaceId != null) + PopupMenuItem( + value: ChatContextAction.removeFromSpace, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.delete_sweep_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.removeFromSpace), + ], + ), + ), + // Pangea# + PopupMenuItem( + value: ChatContextAction.leave, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.delete_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.leave), + ], + ), + ), + ], + ); + + if (action == null) return; + if (!mounted) return; + + switch (action) { + case ChatContextAction.open: + onChatTap(room); + return; + case ChatContextAction.goToSpace: + setActiveSpace(space!.id); + return; + case ChatContextAction.favorite: + await showFutureLoadingDialog( + context: context, + future: () => room.setFavourite(!room.isFavourite), + ); + return; + case ChatContextAction.markUnread: + await showFutureLoadingDialog( + context: context, + future: () => room.markUnread(!room.markedUnread), + ); + return; + case ChatContextAction.mute: + await showFutureLoadingDialog( + context: context, + future: () => room.setPushRuleState( + room.pushRuleState == PushRuleState.notify + ? PushRuleState.mentionsOnly + : PushRuleState.notify, + ), + ); + return; + case ChatContextAction.leave: + final confirmed = await showOkCancelAlertDialog( useRootNavigator: false, context: context, title: L10n.of(context)!.areYouSure, - okLabel: L10n.of(context)!.yes, - cancelLabel: L10n.of(context)!.cancel, - message: onlyAdmin && selectedRoomIds.length == 1 - ? L10n.of(context)!.onlyAdminDescription - : L10n.of(context)!.leaveRoomDescription, - ) == - OkCancelResult.ok; - if (!confirmed) return; - final bool leftActiveRoom = - selectedRoomIds.contains(Matrix.of(context).activeRoomId); - await showFutureLoadingDialog( - context: context, - future: () => _leaveSelectedRooms(onlyAdmin), - ); - if (leftActiveRoom) { - context.go('/rooms'); + okLabel: L10n.of(context)!.leave, + cancelLabel: L10n.of(context)!.no, + message: L10n.of(context)!.archiveRoomDescription, + isDestructiveAction: true, + ); + if (confirmed == OkCancelResult.cancel) return; + if (!mounted) return; + + await showFutureLoadingDialog(context: context, future: room.leave); + + return; + case ChatContextAction.addToSpace: + final space = await showConfirmationDialog( + context: context, + title: L10n.of(context)!.space, + actions: spacesWithPowerLevels + .map( + (space) => AlertDialogAction( + key: space, + label: space + .getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), + ), + ) + .toList(), + ); + if (space == null) return; + await showFutureLoadingDialog( + context: context, + // #Pangea + // future: () => space.setSpaceChild(room.id), + future: () => space.pangeaSetSpaceChild(room.id), + // Pangea# + ); + // #Pangea + return; + case ChatContextAction.removeFromSpace: + await showFutureLoadingDialog( + context: context, + future: () async { + final futures = room.pangeaSpaceParents + .where((r) => r.canChangeStateEvent(EventTypes.SpaceChild)) + .map((space) => removeSpaceChild(space, room.id)); + await Future.wait(futures); + }, + ); + return; + // Pangea# + } + } + + // #Pangea + // Remove a room from a space. Often, the user will have permission to set + // the SpaceChild event for the parent space, but not the SpaceParent event. + // This would cause a permissions error, but the child will still be removed + // via the SpaceChild event. If that's the case, silence the error. + Future removeSpaceChild(Room space, String roomId) async { + try { + await space.removeSpaceChild(roomId); + } catch (err) { + if ((err as MatrixException).error != MatrixError.M_FORBIDDEN) { + rethrow; + } } } // Pangea# @@ -770,140 +989,6 @@ class ChatListController extends State ); } - Future _archiveSelectedRooms() async { - final client = Matrix.of(context).client; - while (selectedRoomIds.isNotEmpty) { - final roomId = selectedRoomIds.first; - try { - // #Pangea - // await client.getRoomById(roomId)!.leave(); - await client.getRoomById(roomId)!.archive(); - // Pangea# - } finally { - toggleSelection(roomId); - } - } - } - - // #Pangea - Future _leaveSelectedRooms(bool onlyAdmin) async { - final client = Matrix.of(context).client; - while (selectedRoomIds.isNotEmpty) { - final roomId = selectedRoomIds.first; - try { - final room = client.getRoomById(roomId); - if (!room!.isSpace && - room.membership == Membership.join && - room.isUnread) { - await room.markUnread(false); - } - onlyAdmin ? await room.archive() : await room.leave(); - } finally { - toggleSelection(roomId); - } - } - } - // Pangea# - - Future addToSpace() async { - // #Pangea - final firstSelectedRoom = - Matrix.of(context).client.getRoomById(selectedRoomIds.toList().first); - // Pangea# - final selectedSpace = await showConfirmationDialog( - context: context, - title: L10n.of(context)!.addToSpace, - // #Pangea - // message: L10n.of(context)!.addToSpaceDescription, - message: L10n.of(context)!.addSpaceToSpaceDescription, - // Pangea# - fullyCapitalizedForMaterial: false, - actions: Matrix.of(context) - .client - .rooms - .where( - (r) => - r.isSpace - // #Pangea - && - selectedRoomIds - .map((id) => Matrix.of(context).client.getRoomById(id)) - // Only show non-recursion-causing spaces - // Performs a few other checks as well - .every((e) => r.canAddAsParentOf(e)), - //Pangea# - ) - .map( - (space) => AlertDialogAction( - key: space.id, - // #Pangea - // label: space - // .getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), - label: space.nameIncludingParents(context), - // If user is not admin of space, button is grayed out - textStyle: TextStyle( - color: (firstSelectedRoom == null) - ? Theme.of(context).colorScheme.outline - : Theme.of(context).colorScheme.surfaceTint, - ), - // Pangea# - ), - ) - .toList(), - ); - if (selectedSpace == null) return; - final result = await showFutureLoadingDialog( - context: context, - future: () async { - final space = Matrix.of(context).client.getRoomById(selectedSpace)!; - // #Pangea - if (firstSelectedRoom == null) { - throw L10n.of(context)!.nonexistentSelection; - } - - if (space.canSendDefaultStates) { - for (final roomId in selectedRoomIds) { - await space.pangeaSetSpaceChild(roomId, suggested: true); - } - } - // Pangea# - }, - ); - if (result.error == null) { - if (!mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - // #Pangea - // content: Text(L10n.of(context)!.chatHasBeenAddedToThisSpace), - content: Text(L10n.of(context)!.roomAddedToSpace), - // Pangea# - ), - ); - } - - // #Pangea - // setState(() => selectedRoomIds.clear()); - if (firstSelectedRoom != null) { - toggleSelection(firstSelectedRoom.id); - } - // Pangea# - } - - bool get anySelectedRoomNotMarkedUnread => selectedRoomIds.any( - (roomId) => - !Matrix.of(context).client.getRoomById(roomId)!.markedUnread, - ); - - bool get anySelectedRoomNotFavorite => selectedRoomIds.any( - (roomId) => !Matrix.of(context).client.getRoomById(roomId)!.isFavourite, - ); - - bool get anySelectedRoomNotMuted => selectedRoomIds.any( - (roomId) => - Matrix.of(context).client.getRoomById(roomId)!.pushRuleState == - PushRuleState.notify, - ); - bool waitForFirstSync = false; Future _waitForFirstSync() async { @@ -931,6 +1016,8 @@ class ChatListController extends State } // #Pangea + MatrixState.pangeaController.myAnalytics.initialize(); + MatrixState.pangeaController.analytics.initialize(); await _initPangeaControllers(client); // Pangea# if (!mounted) return; @@ -942,10 +1029,10 @@ class ChatListController extends State // #Pangea Future _initPangeaControllers(Client client) async { if (mounted) { + final PangeaController pangeaController = MatrixState.pangeaController; GoogleAnalytics.analyticsUserUpdate(client.userID); pangeaController.startChatWithBotIfNotPresent(); await pangeaController.subscriptionController.initialize(); - await pangeaController.myAnalytics.initialize(); pangeaController.afterSyncAndFirstLoginInitialization(context); await pangeaController.inviteBotToExistingSpaces(); await pangeaController.setPangeaPushRules(); @@ -961,24 +1048,20 @@ class ChatListController extends State void cancelAction() { if (selectMode == SelectMode.share) { setState(() => Matrix.of(context).shareContent = null); - } else { - // #Pangea - // setState(() => selectedRoomIds.clear()); - for (final roomId in selectedRoomIds.toList()) { - toggleSelection(roomId); - } - // Pangea# } } + void setActiveFilter(ActiveFilter filter) { + setState(() { + activeFilter = filter; + }); + } + void setActiveClient(Client client) { context.go('/rooms'); setState(() { - activeFilter = AppConfig.separateChatTypes - ? ActiveFilter.messages - : ActiveFilter.allChats; - activeSpaceId = null; - selectedRoomIds.clear(); + activeFilter = ActiveFilter.allChats; + _activeSpaceId = null; Matrix.of(context).setActiveClient(client); }); _clientStream.add(client); @@ -987,7 +1070,7 @@ class ChatListController extends State void setActiveBundle(String bundle) { context.go('/rooms'); setState(() { - selectedRoomIds.clear(); + _activeSpaceId = null; Matrix.of(context).activeBundle = bundle; if (!Matrix.of(context) .currentBundle! @@ -1080,3 +1163,138 @@ class ChatListController extends State } enum EditBundleAction { addToBundle, removeFromBundle } + +enum InviteActions { + accept, + decline, + block, +} + +enum ChatContextAction { + open, + goToSpace, + favorite, + markUnread, + mute, + leave, + addToSpace, + // #Pangea + removeFromSpace, + // Pangea# +} + +// TODO re-integrate this logic +// // #Pangea +// Future leaveAction() async { +// final onlyAdmin = await Matrix.of(context) +// .client +// .getRoomById(selectedRoomIds.first) +// ?.isOnlyAdmin() ?? +// false; +// final confirmed = await showOkCancelAlertDialog( +// useRootNavigator: false, +// context: context, +// title: L10n.of(context)!.areYouSure, +// okLabel: L10n.of(context)!.yes, +// cancelLabel: L10n.of(context)!.cancel, +// message: onlyAdmin && selectedRoomIds.length == 1 +// ? L10n.of(context)!.onlyAdminDescription +// : L10n.of(context)!.leaveRoomDescription, +// ) == +// OkCancelResult.ok; +// if (!confirmed) return; +// final leftActiveRoom = +// selectedRoomIds.contains(Matrix.of(context).activeRoomId); +// await showFutureLoadingDialog( +// context: context, +// future: () => _leaveSelectedRooms(onlyAdmin), +// ); +// if (leftActiveRoom) { +// context.go('/rooms'); +// } +// } +// // Pangea# + +// Future addToSpace() async { +// // #Pangea +// final firstSelectedRoom = +// Matrix.of(context).client.getRoomById(selectedRoomIds.toList().first); +// // Pangea# +// final selectedSpace = await showConfirmationDialog( +// context: context, +// title: L10n.of(context)!.addToSpace, +// // #Pangea +// // message: L10n.of(context)!.addToSpaceDescription, +// message: L10n.of(context)!.addSpaceToSpaceDescription, +// // Pangea# +// fullyCapitalizedForMaterial: false, +// actions: Matrix.of(context) +// .client +// .rooms +// .where( +// (r) => +// r.isSpace +// // #Pangea +// && +// selectedRoomIds +// .map((id) => Matrix.of(context).client.getRoomById(id)) +// // Only show non-recursion-causing spaces +// // Performs a few other checks as well +// .every((e) => r.canAddAsParentOf(e)), +// //Pangea# +// ) +// .map( +// (space) => AlertDialogAction( +// key: space.id, +// // #Pangea +// // label: space +// // .getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), +// label: space.nameIncludingParents(context), +// // If user is not admin of space, button is grayed out +// textStyle: TextStyle( +// color: (firstSelectedRoom == null) +// ? Theme.of(context).colorScheme.outline +// : Theme.of(context).colorScheme.surfaceTint, +// ), +// // Pangea# +// ), +// ) +// .toList(), +// ); +// if (selectedSpace == null) return; +// final result = await showFutureLoadingDialog( +// context: context, +// future: () async { +// final space = Matrix.of(context).client.getRoomById(selectedSpace)!; +// // #Pangea +// if (firstSelectedRoom == null) { +// throw L10n.of(context)!.nonexistentSelection; +// } + +// if (space.canSendDefaultStates) { +// for (final roomId in selectedRoomIds) { +// await space.pangeaSetSpaceChild(roomId, suggested: true); +// } +// } +// // Pangea# +// }, +// ); +// if (result.error == null) { +// if (!mounted) return; +// ScaffoldMessenger.of(context).showSnackBar( +// SnackBar( +// // #Pangea +// // content: Text(L10n.of(context)!.chatHasBeenAddedToThisSpace), +// content: Text(L10n.of(context)!.roomAddedToSpace), +// // Pangea# +// ), +// ); +// } + +// // #Pangea +// // setState(() => selectedRoomIds.clear()); +// if (firstSelectedRoom != null) { +// toggleSelection(firstSelectedRoom.id); +// } +// // Pangea# +// } diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index b9b388da9..19e46b9ae 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -1,15 +1,17 @@ -import 'package:animations/animations.dart'; +import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; +import 'package:fluffychat/pages/chat_list/chat_list_header.dart'; +import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; +import 'package:fluffychat/pages/chat_list/dummy_chat_list_item.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart'; import 'package:fluffychat/pages/chat_list/space_view.dart'; import 'package:fluffychat/pages/user_bottom_sheet/user_bottom_sheet.dart'; -import 'package:fluffychat/pangea/widgets/chat_list/chat_list_body_text.dart'; -import 'package:fluffychat/pangea/widgets/chat_list/chat_list_header_wrapper.dart'; -import 'package:fluffychat/pangea/widgets/chat_list/chat_list_item_wrapper.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; +import 'package:fluffychat/widgets/hover_builder.dart'; import 'package:fluffychat/widgets/public_room_bottom_sheet.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; @@ -25,6 +27,34 @@ class ChatListViewBody extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + + final client = Matrix.of(context).client; + final activeSpace = controller.activeSpaceId; + if (activeSpace != null) { + return SpaceView( + spaceId: activeSpace, + onBack: controller.clearActiveSpace, + onChatTab: (room) => controller.onChatTap(room), + onChatContext: (room, context) => + controller.chatContextAction(room, context), + activeChat: controller.activeChat, + toParentSpace: controller.setActiveSpace, + // #Pangea + controller: controller, + // Pangea# + ); + } + final spaces = client.rooms.where((r) => r.isSpace); + final spaceDelegateCandidates = {}; + for (final space in spaces) { + for (final spaceChild in space.spaceChildren) { + final roomId = spaceChild.roomId; + if (roomId == null) continue; + spaceDelegateCandidates[roomId] = space; + } + } + final publicRooms = controller.roomSearchResult?.chunk .where((room) => room.roomType != 'm.space') .toList(); @@ -32,249 +62,270 @@ class ChatListViewBody extends StatelessWidget { .where((room) => room.roomType == 'm.space') .toList(); final userSearchResult = controller.userSearchResult; - final client = Matrix.of(context).client; const dummyChatCount = 4; - final titleColor = - Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(100); - final subtitleColor = - Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(50); final filter = controller.searchController.text.toLowerCase(); - return PageTransitionSwitcher( - transitionBuilder: ( - Widget child, - Animation primaryAnimation, - Animation secondaryAnimation, - ) { - return SharedAxisTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - transitionType: SharedAxisTransitionType.vertical, - fillColor: Theme.of(context).scaffoldBackgroundColor, - child: child, - ); - }, - child: StreamBuilder( - key: ValueKey( - client.userID.toString() + - controller.activeFilter.toString() + - controller.activeSpaceId.toString(), - ), - stream: client.onSync.stream - .where((s) => s.hasRoomUpdate) - .rateLimit(const Duration(seconds: 1)), - builder: (context, _) { - if (controller.activeFilter == ActiveFilter.spaces) { - return SpaceView( - controller, - scrollController: controller.scrollController, - key: Key(controller.activeSpaceId ?? 'Spaces'), - ); - } - final rooms = controller.filteredRooms; - return SafeArea( - child: CustomScrollView( - controller: controller.scrollController, - slivers: [ - // #Pangea - // ChatListHeader(controller: controller), - ChatListHeaderWrapper(controller: controller), - // Pangea# - SliverList( - delegate: SliverChildListDelegate( - [ - if (controller.isSearchMode) ...[ - SearchTitle( - title: L10n.of(context)!.publicRooms, - icon: const Icon(Icons.explore_outlined), + return StreamBuilder( + key: ValueKey( + client.userID.toString(), + ), + stream: client.onSync.stream + .where((s) => s.hasRoomUpdate) + .rateLimit(const Duration(seconds: 1)), + builder: (context, _) { + final rooms = controller.filteredRooms; + + return SafeArea( + child: CustomScrollView( + controller: controller.scrollController, + slivers: [ + ChatListHeader(controller: controller), + SliverList( + delegate: SliverChildListDelegate( + [ + if (controller.isSearchMode) ...[ + SearchTitle( + title: L10n.of(context)!.publicRooms, + icon: const Icon(Icons.explore_outlined), + ), + PublicRoomsHorizontalList(publicRooms: publicRooms), + SearchTitle( + title: L10n.of(context)!.publicSpaces, + icon: const Icon(Icons.workspaces_outlined), + ), + PublicRoomsHorizontalList(publicRooms: publicSpaces), + SearchTitle( + title: L10n.of(context)!.users, + icon: const Icon(Icons.group_outlined), + ), + AnimatedContainer( + clipBehavior: Clip.hardEdge, + decoration: const BoxDecoration(), + height: userSearchResult == null || + userSearchResult.results.isEmpty + ? 0 + : 106, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + child: userSearchResult == null + ? null + : ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: userSearchResult.results.length, + itemBuilder: (context, i) => _SearchItem( + title: + userSearchResult.results[i].displayName ?? + userSearchResult + .results[i].userId.localpart ?? + L10n.of(context)!.unknownDevice, + avatar: userSearchResult.results[i].avatarUrl, + onPressed: () => showAdaptiveBottomSheet( + context: context, + builder: (c) => UserBottomSheet( + profile: userSearchResult.results[i], + outerContext: context, + ), + ), + ), + ), + ), + ], + // #Pangea + // if (!controller.isSearchMode && AppConfig.showPresences) + // GestureDetector( + // onLongPress: () => controller.dismissStatusList(), + // child: StatusMessageList( + // onStatusEdit: controller.setStatus, + // ), + // ), + // Pangea# + const ConnectionStatusHeader(), + AnimatedContainer( + height: controller.isTorBrowser ? 64 : 0, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + clipBehavior: Clip.hardEdge, + decoration: const BoxDecoration(), + child: Material( + color: theme.colorScheme.surface, + child: ListTile( + leading: const Icon(Icons.vpn_key), + title: Text(L10n.of(context)!.dehydrateTor), + subtitle: Text(L10n.of(context)!.dehydrateTorLong), + trailing: const Icon(Icons.chevron_right_outlined), + onTap: controller.dehydrate, ), - PublicRoomsHorizontalList(publicRooms: publicRooms), - SearchTitle( - title: L10n.of(context)!.publicSpaces, - icon: const Icon(Icons.workspaces_outlined), - ), - PublicRoomsHorizontalList(publicRooms: publicSpaces), - SearchTitle( - title: L10n.of(context)!.users, - icon: const Icon(Icons.group_outlined), - ), - AnimatedContainer( - clipBehavior: Clip.hardEdge, - decoration: const BoxDecoration(), - height: userSearchResult == null || - userSearchResult.results.isEmpty - ? 0 - : 106, - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - child: userSearchResult == null - ? null - : ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: userSearchResult.results.length, - itemBuilder: (context, i) => _SearchItem( - title: userSearchResult - .results[i].displayName ?? - userSearchResult - .results[i].userId.localpart ?? - L10n.of(context)!.unknownDevice, - avatar: - userSearchResult.results[i].avatarUrl, - onPressed: () => showAdaptiveBottomSheet( - context: context, - builder: (c) => UserBottomSheet( - profile: userSearchResult.results[i], - outerContext: context, + ), + ), + if (client.rooms.isNotEmpty && !controller.isSearchMode) + SizedBox( + height: 64, + child: ListView( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 16.0, + ), + shrinkWrap: true, + scrollDirection: Axis.horizontal, + children: [ + if (AppConfig.separateChatTypes) + ActiveFilter.messages + else + ActiveFilter.allChats, + ActiveFilter.groups, + ActiveFilter.unread, + if (spaceDelegateCandidates.isNotEmpty && + !controller.widget.displayNavigationRail) + ActiveFilter.spaces, + ] + .map( + (filter) => Padding( + padding: + const EdgeInsets.symmetric(horizontal: 4), + child: HoverBuilder( + builder: (context, hovered) => + AnimatedScale( + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + scale: hovered ? 1.1 : 1.0, + child: InkWell( + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), + onTap: () => + controller.setActiveFilter(filter), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 6, + ), + decoration: BoxDecoration( + color: filter == + controller.activeFilter + ? theme.colorScheme.primary + : theme.colorScheme + .secondaryContainer, + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), + ), + alignment: Alignment.center, + child: Text( + filter.toLocalizedString(context), + style: TextStyle( + fontWeight: filter == + controller.activeFilter + ? FontWeight.bold + : FontWeight.normal, + color: filter == + controller.activeFilter + ? theme.colorScheme.onPrimary + : theme.colorScheme + .onSecondaryContainer, + ), + ), + ), ), ), ), ), - ), - ], - // #Pangea - // if (!controller.isSearchMode && - // controller.activeFilter != ActiveFilter.groups && - // AppConfig.showPresences) - // GestureDetector( - // onLongPress: () => controller.dismissStatusList(), - // child: StatusMessageList( - // onStatusEdit: controller.setStatus, - // ), - // ), - // Pangea# - const ConnectionStatusHeader(), - AnimatedContainer( - height: controller.isTorBrowser ? 64 : 0, - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - clipBehavior: Clip.hardEdge, - decoration: const BoxDecoration(), - child: Material( - color: Theme.of(context).colorScheme.surface, - child: ListTile( - leading: const Icon(Icons.vpn_key), - title: Text(L10n.of(context)!.dehydrateTor), - subtitle: Text(L10n.of(context)!.dehydrateTorLong), - trailing: const Icon(Icons.chevron_right_outlined), - onTap: controller.dehydrate, - ), + ) + .toList(), ), ), - if (controller.isSearchMode) - SearchTitle( - title: L10n.of(context)!.chats, - icon: const Icon(Icons.forum_outlined), - ), - if (client.prevBatch != null && - rooms.isEmpty && - !controller.isSearchMode) ...[ - // #Pangea - // Padding( - // padding: const EdgeInsets.all(32.0), - // child: Icon( - // CupertinoIcons.chat_bubble_2, - // size: 128, - // color: - // Theme.of(context).colorScheme.onInverseSurface, - // ), - // ), - Center( - child: ChatListBodyStartText( - controller: controller, - ), - ), - // Pangea# - ], - ], - ), - ), - if (client.prevBatch == null) - SliverList( - delegate: SliverChildBuilderDelegate( - (context, i) => Opacity( - opacity: (dummyChatCount - i) / dummyChatCount, - child: ListTile( - leading: CircleAvatar( - backgroundColor: titleColor, - child: CircularProgressIndicator( - strokeWidth: 1, - color: - Theme.of(context).textTheme.bodyLarge!.color, - ), - ), - title: Row( + if (controller.isSearchMode) + SearchTitle( + title: L10n.of(context)!.chats, + icon: const Icon(Icons.forum_outlined), + ), + if (client.prevBatch != null && + rooms.isEmpty && + !controller.isSearchMode) ...[ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Stack( + alignment: Alignment.center, children: [ - Expanded( - child: Container( - height: 14, - decoration: BoxDecoration( - color: titleColor, - borderRadius: BorderRadius.circular(3), + const Column( + mainAxisSize: MainAxisSize.min, + children: [ + DummyChatListItem( + opacity: 0.5, + animate: false, ), - ), + DummyChatListItem( + opacity: 0.3, + animate: false, + ), + ], ), - const SizedBox(width: 36), - Container( - height: 14, - width: 14, - decoration: BoxDecoration( - color: subtitleColor, - borderRadius: BorderRadius.circular(14), - ), - ), - const SizedBox(width: 12), - Container( - height: 14, - width: 14, - decoration: BoxDecoration( - color: subtitleColor, - borderRadius: BorderRadius.circular(14), - ), + Icon( + CupertinoIcons.chat_bubble_text_fill, + size: 128, + color: theme.colorScheme.secondary, ), ], ), - subtitle: Container( - decoration: BoxDecoration( - color: subtitleColor, - borderRadius: BorderRadius.circular(3), + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + client.rooms.isEmpty + ? L10n.of(context)!.noChatsFoundHere + : L10n.of(context)!.noMoreChatsFound, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: theme.colorScheme.secondary, + ), ), - height: 12, - margin: const EdgeInsets.only(right: 22), ), - ), + ], ), - childCount: dummyChatCount, + // Padding( + // padding: const EdgeInsets.all(32.0), + // child: Icon( + // CupertinoIcons.chat_bubble_2, + // size: 128, + // color: theme.colorScheme.secondary, + // ), + // ), + // Pangea# + ], + ], + ), + ), + if (client.prevBatch == null) + SliverList( + delegate: SliverChildBuilderDelegate( + (context, i) => DummyChatListItem( + opacity: (dummyChatCount - i) / dummyChatCount, + animate: true, ), + childCount: dummyChatCount, ), - if (client.prevBatch != null) - SliverList.builder( - itemCount: rooms.length, - itemBuilder: (BuildContext context, int i) { - // #Pangea - // return ChatListItem( - return ChatListItemWrapper( - controller: controller, - // Pangea# - rooms[i], - key: Key('chat_list_item_${rooms[i].id}'), - filter: filter, - // #Pangea - // selected: - // controller.selectedRoomIds.contains(rooms[i].id), - // onTap: controller.selectMode == SelectMode.select - // ? () => controller.toggleSelection(rooms[i].id) - // : () => onChatTap(rooms[i], context), - // onLongPress: () => - // controller.toggleSelection(rooms[i].id), - // Pangea# - activeChat: controller.activeChat == rooms[i].id, - ); - }, - ), - ], - ), - ); - }, - ), + ), + if (client.prevBatch != null) + SliverList.builder( + itemCount: rooms.length, + itemBuilder: (BuildContext context, int i) { + final room = rooms[i]; + final space = spaceDelegateCandidates[room.id]; + return ChatListItem( + room, + space: space, + key: Key('chat_list_item_${room.id}'), + filter: filter, + onTap: () => controller.onChatTap(room), + onLongPress: (context) => + controller.chatContextAction(room, context, space), + activeChat: controller.activeChat == room.id, + ); + }, + ), + ], + ), + ); + }, ); } } diff --git a/lib/pages/chat_list/chat_list_header.dart b/lib/pages/chat_list/chat_list_header.dart index a45751201..4c018355c 100644 --- a/lib/pages/chat_list/chat_list_header.dart +++ b/lib/pages/chat_list/chat_list_header.dart @@ -1,8 +1,7 @@ import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; import 'package:fluffychat/pages/chat_list/client_chooser_button.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -18,11 +17,13 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final selectMode = controller.selectMode; return SliverAppBar( floating: true, - toolbarHeight: 72, + toolbarHeight: 175, pinned: FluffyThemes.isColumnMode(context) || selectMode != SelectMode.normal, scrolledUnderElevation: selectMode == SelectMode.normal ? 0 : null, @@ -37,40 +38,39 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { tooltip: L10n.of(context)!.cancel, icon: const Icon(Icons.close_outlined), onPressed: controller.cancelAction, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), - title: + title: selectMode == SelectMode.share + ? Text( + L10n.of(context)!.share, + key: const ValueKey(SelectMode.share), + ) // #Pangea - Material( - child: - // Pangea# - selectMode == SelectMode.share - ? Text( - L10n.of(context)!.share, - key: const ValueKey(SelectMode.share), - ) - : selectMode == SelectMode.select - ? Text( - controller.selectedRoomIds.length.toString(), - key: const ValueKey(SelectMode.select), - ) - // #Pangea - : ClientChooserButton(controller), - ), + : Column( + children: [ + ClientChooserButton(controller), + const LearningProgressIndicators(), + ], + ), // : TextField( // controller: controller.searchController, // focusNode: controller.searchFocusNode, // textInputAction: TextInputAction.search, - // onChanged: controller.onSearchEnter, + // onChanged: (text) => controller.onSearchEnter( + // text, + // globalSearch: globalSearch, + // ), // decoration: InputDecoration( - // fillColor: Theme.of(context).colorScheme.secondaryContainer, - // border: UnderlineInputBorder( + // filled: true, + // fillColor: theme.colorScheme.secondaryContainer, + // border: OutlineInputBorder( // borderSide: BorderSide.none, // borderRadius: BorderRadius.circular(99), // ), + // contentPadding: EdgeInsets.zero, // hintText: L10n.of(context)!.searchChatsRooms, // hintStyle: TextStyle( - // color: Theme.of(context).colorScheme.onPrimaryContainer, + // color: theme.colorScheme.onPrimaryContainer, // fontWeight: FontWeight.normal, // ), // floatingLabelBehavior: FloatingLabelBehavior.never, @@ -79,20 +79,16 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { // tooltip: L10n.of(context)!.cancel, // icon: const Icon(Icons.close_outlined), // onPressed: controller.cancelSearch, - // color: Theme.of(context) - // .colorScheme - // .onPrimaryContainer, + // color: theme.colorScheme.onPrimaryContainer, // ) // : IconButton( // onPressed: controller.startSearch, // icon: Icon( // Icons.search_outlined, - // color: Theme.of(context) - // .colorScheme - // .onPrimaryContainer, + // color: theme.colorScheme.onPrimaryContainer, // ), // ), - // suffixIcon: controller.isSearchMode + // suffixIcon: controller.isSearchMode && globalSearch // ? controller.isSearching // ? const Padding( // padding: EdgeInsets.symmetric( @@ -117,10 +113,7 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { // icon: const Icon(Icons.edit_outlined, size: 16), // label: Text( // controller.searchServer ?? - // Matrix.of(context) - // .client - // .homeserver! - // .host, + // Matrix.of(context).client.homeserver!.host, // maxLines: 2, // ), // ) @@ -143,80 +136,7 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { // ), // Pangea# ] - : selectMode == SelectMode.select - ? [ - // #Pangea - // if (controller.spaces.isNotEmpty) - if (controller.spaces.isNotEmpty && - controller.selectedRoomIds.length == 1) - // Pangea# - IconButton( - tooltip: L10n.of(context)!.addToSpace, - icon: const Icon(Icons.workspaces_outlined), - onPressed: controller.addToSpace, - ), - IconButton( - tooltip: L10n.of(context)!.toggleUnread, - icon: Icon( - controller.anySelectedRoomNotMarkedUnread - ? Icons.mark_chat_unread_outlined - : Icons.mark_chat_read_outlined, - ), - onPressed: controller.toggleUnread, - ), - IconButton( - tooltip: L10n.of(context)!.toggleFavorite, - icon: Icon( - controller.anySelectedRoomNotFavorite - ? Icons.push_pin - : Icons.push_pin_outlined, - ), - onPressed: controller.toggleFavouriteRoom, - ), - IconButton( - icon: Icon( - controller.anySelectedRoomNotMuted - ? Icons.notifications_off_outlined - : Icons.notifications_outlined, - ), - tooltip: L10n.of(context)!.toggleMuted, - onPressed: controller.toggleMuted, - ), - // #Pangea - if (controller.selectedRoomIds.length > 1) - IconButton( - icon: const Icon(Icons.arrow_forward), - tooltip: L10n.of(context)!.leave, - onPressed: controller.leaveAction, - ), - if (controller.selectedRoomIds.length == 1 && - !(Matrix.of(context) - .client - .getRoomById(controller.selectedRoomIds.single) - ?.isRoomAdmin ?? - false)) - IconButton( - icon: const Icon(Icons.arrow_forward), - tooltip: L10n.of(context)!.leave, - onPressed: controller.leaveAction, - ), - if (controller.selectedRoomIds.length == 1 && - (Matrix.of(context) - .client - .getRoomById(controller.selectedRoomIds.single) - ?.isRoomAdmin ?? - false)) - // Pangea# - IconButton( - // #Pangea - // icon: const Icon(Icons.delete_outlined), - icon: const Icon(Icons.archive_outlined), - // Pangea# - tooltip: L10n.of(context)!.archive, - onPressed: controller.archiveAction, - ), - ] - : null, + : null, ); } diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 76c75e83b..9cbe6af82 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -19,9 +19,9 @@ enum ArchivedRoomAction { delete, rejoin } class ChatListItem extends StatelessWidget { final Room room; + final Room? space; final bool activeChat; - final bool selected; - final void Function()? onLongPress; + final void Function(BuildContext context)? onLongPress; final void Function()? onForget; final void Function() onTap; final String? filter; @@ -29,11 +29,11 @@ class ChatListItem extends StatelessWidget { const ChatListItem( this.room, { this.activeChat = false, - this.selected = false, required this.onTap, this.onLongPress, this.onForget, this.filter, + this.space, super.key, }); @@ -57,10 +57,7 @@ class ChatListItem extends StatelessWidget { if (confirmed == OkCancelResult.cancel) return; await showFutureLoadingDialog( context: context, - // #Pangea - // future: () => room.leave(), - future: () => room.archive(), - // Pangea# + future: () => room.leave(), ); return; } @@ -68,12 +65,13 @@ class ChatListItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final isMuted = room.pushRuleState != PushRuleState.notify; final typingText = room.getLocalizedTypingText(context); final lastEvent = room.lastEvent; final ownMessage = lastEvent?.senderId == room.client.userID; final unread = room.isUnread || room.membership == Membership.invite; - final theme = Theme.of(context); final directChatMatrixId = room.directChatMatrixID; final isDirectChat = directChatMatrixId != null; final unreadBubbleSize = unread || room.hasNewMessages @@ -82,11 +80,8 @@ class ChatListItem extends StatelessWidget { : 14.0 : 0.0; final hasNotifications = room.notificationCount > 0; - final backgroundColor = selected - ? theme.colorScheme.primaryContainer - : activeChat - ? theme.colorScheme.secondaryContainer - : null; + final backgroundColor = + activeChat ? theme.colorScheme.secondaryContainer : null; final displayname = room.getLocalizedDisplayname( MatrixLocals(L10n.of(context)!), ); @@ -98,6 +93,7 @@ class ChatListItem extends StatelessWidget { final needLastEventSender = lastEvent == null ? false : room.getState(EventTypes.RoomMember, lastEvent.senderId) == null; + final space = this.space; return Padding( padding: const EdgeInsets.symmetric( @@ -111,50 +107,89 @@ class ChatListItem extends StatelessWidget { child: FutureBuilder( future: room.loadHeroUsers(), builder: (context, snapshot) => HoverBuilder( - builder: (context, hovered) => ListTile( + builder: (context, listTileHovered) => ListTile( visualDensity: const VisualDensity(vertical: -0.5), contentPadding: const EdgeInsets.symmetric(horizontal: 8), - onLongPress: onLongPress, - leading: Stack( - clipBehavior: Clip.none, - children: [ - HoverBuilder( - builder: (context, hovered) => AnimatedScale( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - scale: hovered ? 1.1 : 1.0, - child: Avatar( - mxContent: room.avatar, - name: displayname, - //#Pangea - littleIcon: room.roomTypeIcon, - // Pangea# - presenceUserId: directChatMatrixId, - presenceBackgroundColor: backgroundColor, - onTap: onLongPress, - ), - ), - ), - Positioned( - bottom: -2, - right: -2, - child: AnimatedScale( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - scale: (hovered || selected) ? 1.0 : 0.0, - child: Material( - color: backgroundColor, - borderRadius: BorderRadius.circular(16), - child: Icon( - selected - ? Icons.check_circle - : Icons.check_circle_outlined, - size: 18, + onLongPress: () => onLongPress?.call(context), + leading: HoverBuilder( + builder: (context, hovered) => AnimatedScale( + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + scale: hovered ? 1.1 : 1.0, + child: SizedBox( + width: Avatar.defaultSize, + height: Avatar.defaultSize, + child: Stack( + children: [ + if (space != null) + Positioned( + top: 0, + left: 0, + child: Avatar( + border: BorderSide( + width: 2, + color: backgroundColor ?? + theme.colorScheme.surface, + ), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 4, + ), + mxContent: space.avatar, + size: Avatar.defaultSize * 0.75, + name: space.getLocalizedDisplayname(), + onTap: () => onLongPress?.call(context), + ), + ), + Positioned( + bottom: 0, + right: 0, + child: Avatar( + border: space == null + ? null + : BorderSide( + width: 2, + color: backgroundColor ?? + theme.colorScheme.surface, + ), + borderRadius: room.isSpace + ? BorderRadius.circular( + AppConfig.borderRadius / 4, + ) + : null, + mxContent: room.avatar, + size: space != null + ? Avatar.defaultSize * 0.75 + : Avatar.defaultSize, + name: displayname, + presenceUserId: directChatMatrixId, + presenceBackgroundColor: backgroundColor, + onTap: () => onLongPress?.call(context), + ), ), - ), + Positioned( + top: 0, + right: 0, + child: GestureDetector( + onTap: () => onLongPress?.call(context), + child: AnimatedScale( + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + scale: listTileHovered ? 1.0 : 0.0, + child: Material( + color: backgroundColor, + borderRadius: BorderRadius.circular(16), + child: const Icon( + Icons.arrow_drop_down_circle_outlined, + size: 18, + ), + ), + ), + ), + ), + ], ), ), - ], + ), ), title: Row( children: [ @@ -188,7 +223,9 @@ class ChatListItem extends StatelessWidget { color: theme.colorScheme.primary, ), ), - if (lastEvent != null && room.membership != Membership.invite) + if (!room.isSpace && + lastEvent != null && + room.membership != Membership.invite) Padding( padding: const EdgeInsets.only(left: 4.0), child: Text( @@ -201,6 +238,11 @@ class ChatListItem extends StatelessWidget { ), ), ), + if (room.isSpace) + const Icon( + Icons.arrow_circle_right_outlined, + size: 18, + ), ], ), subtitle: Row( @@ -230,61 +272,82 @@ class ChatListItem extends StatelessWidget { ), ), Expanded( - child: typingText.isNotEmpty + child: room.isSpace && room.membership == Membership.join ? Text( - typingText, - style: TextStyle( - color: theme.colorScheme.primary, + L10n.of(context)!.countChatsAndCountParticipants( + room.spaceChildren.length.toString(), + (room.summary.mJoinedMemberCount ?? 1).toString(), ), - maxLines: 1, - softWrap: false, ) - // #Pangea - : FutureBuilder( - future: room.lastEvent != null - ? GetChatListItemSubtitle().getSubtitle( - L10n.of(context)!, - room.lastEvent, - MatrixState.pangeaController, - ) - : Future.value(L10n.of(context)!.emptyChat), - builder: (context, snapshot) { - // Pangea# - return Text( - room.membership == Membership.invite - ? isDirectChat - ? L10n.of(context)!.invitePrivateChat - : L10n.of(context)!.inviteGroupChat - // #Pangea - : snapshot.data ?? - // Pangea# - room.lastEvent - ?.calcLocalizedBodyFallback( - MatrixLocals(L10n.of(context)!), - hideReply: true, - hideEdit: true, - plaintextBody: true, - removeMarkdown: true, - withSenderNamePrefix: !isDirectChat || - directChatMatrixId != - room.lastEvent?.senderId, - ) ?? - L10n.of(context)!.emptyChat, - softWrap: false, - maxLines: 1, - overflow: TextOverflow.ellipsis, + : typingText.isNotEmpty + ? Text( + typingText, style: TextStyle( - fontWeight: unread || room.hasNewMessages - ? FontWeight.bold - : null, - color: theme.colorScheme.onSurfaceVariant, - decoration: room.lastEvent?.redacted == true - ? TextDecoration.lineThrough - : null, + color: theme.colorScheme.primary, ), - ); - }, - ), + maxLines: 1, + softWrap: false, + ) + : FutureBuilder( + key: ValueKey( + '${lastEvent?.eventId}_${lastEvent?.type}', + ), + // #Pangea + future: room.lastEvent != null + ? GetChatListItemSubtitle().getSubtitle( + L10n.of(context)!, + room.lastEvent, + MatrixState.pangeaController, + ) + : Future.value(L10n.of(context)!.emptyChat), + // future: needLastEventSender + // ? lastEvent.calcLocalizedBody( + // MatrixLocals(L10n.of(context)!), + // hideReply: true, + // hideEdit: true, + // plaintextBody: true, + // removeMarkdown: true, + // withSenderNamePrefix: (!isDirectChat || + // directChatMatrixId != + // room.lastEvent?.senderId), + // ) + // : null, + // Pangea# + initialData: + lastEvent?.calcLocalizedBodyFallback( + MatrixLocals(L10n.of(context)!), + hideReply: true, + hideEdit: true, + plaintextBody: true, + removeMarkdown: true, + withSenderNamePrefix: (!isDirectChat || + directChatMatrixId != + room.lastEvent?.senderId), + ), + builder: (context, snapshot) => Text( + room.membership == Membership.invite + ? isDirectChat + ? L10n.of(context)!.invitePrivateChat + // #Pangea + // : L10n.of(context)!.inviteGroupChat + : L10n.of(context)!.inviteChat + // Pangea# + : snapshot.data ?? + L10n.of(context)!.emptyChat, + softWrap: false, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: unread || room.hasNewMessages + ? FontWeight.bold + : null, + color: theme.colorScheme.onSurfaceVariant, + decoration: room.lastEvent?.redacted == true + ? TextDecoration.lineThrough + : null, + ), + ), + ), ), const SizedBox(width: 8), // #Pangea diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index 74eef375c..2cc33da06 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -1,101 +1,23 @@ -import 'package:badges/badges.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; import 'package:fluffychat/pages/chat_list/navi_rail_item.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/utils/chat_list_handle_space_tap.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; +import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; -import 'package:fluffychat/widgets/unread_rooms_badge.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; import '../../widgets/matrix.dart'; import 'chat_list_body.dart'; -import 'start_chat_fab.dart'; class ChatListView extends StatelessWidget { final ChatListController controller; const ChatListView(this.controller, {super.key}); - List getNavigationDestinations(BuildContext context) { - final badgePosition = BadgePosition.topEnd(top: -12, end: -8); - return [ - if (AppConfig.separateChatTypes) ...[ - NavigationDestination( - icon: UnreadRoomsBadge( - badgePosition: badgePosition, - filter: - controller.getRoomFilterByActiveFilter(ActiveFilter.messages), - child: const Icon(Icons.chat_outlined), - ), - selectedIcon: UnreadRoomsBadge( - badgePosition: badgePosition, - filter: - controller.getRoomFilterByActiveFilter(ActiveFilter.messages), - child: const Icon(Icons.chat), - ), - //#Pangea - // label: L10n.of(context)!.messages, - label: L10n.of(context)!.directChats, - //Pangea# - ), - NavigationDestination( - icon: UnreadRoomsBadge( - badgePosition: badgePosition, - filter: controller.getRoomFilterByActiveFilter(ActiveFilter.groups), - child: const Icon(Icons.group_outlined), - ), - selectedIcon: UnreadRoomsBadge( - badgePosition: badgePosition, - filter: controller.getRoomFilterByActiveFilter(ActiveFilter.groups), - child: const Icon(Icons.group), - ), - label: L10n.of(context)!.groups, - ), - ] else - NavigationDestination( - icon: UnreadRoomsBadge( - badgePosition: badgePosition, - filter: - controller.getRoomFilterByActiveFilter(ActiveFilter.allChats), - child: const Icon(Icons.chat_outlined), - ), - selectedIcon: UnreadRoomsBadge( - badgePosition: badgePosition, - filter: - controller.getRoomFilterByActiveFilter(ActiveFilter.allChats), - child: const Icon(Icons.chat), - ), - // #Pangea - // label: L10n.of(context)!.chats, - label: L10n.of(context)!.allChats, - // Pangea# - ), - if (controller.spaces.isNotEmpty - // #Pangea - && - !FluffyThemes.isColumnMode(context) - // Pangea# - ) - // #Pangea - // const NavigationDestination( - // icon: Icon(Icons.workspaces_outlined), - // selectedIcon: Icon(Icons.workspaces), - // label: 'Spaces', - // ), - NavigationDestination( - icon: const Icon(Icons.workspaces_outlined), - selectedIcon: const Icon(Icons.workspaces), - label: L10n.of(context)!.allSpaces, - ), - // Pangea# - ]; - } - @override Widget build(BuildContext context) { final client = Matrix.of(context).client; @@ -106,12 +28,13 @@ class ChatListView extends StatelessWidget { return PopScope( canPop: controller.selectMode == SelectMode.normal && !controller.isSearchMode && - controller.activeFilter == - (AppConfig.separateChatTypes - ? ActiveFilter.messages - : ActiveFilter.allChats), - onPopInvoked: (pop) async { + controller.activeSpaceId == null, + onPopInvokedWithResult: (pop, _) { if (pop) return; + if (controller.activeSpaceId != null) { + controller.clearActiveSpace(); + return; + } final selMode = controller.selectMode; if (controller.isSearchMode) { controller.cancelSearch(); @@ -121,23 +44,23 @@ class ChatListView extends StatelessWidget { controller.cancelAction(); return; } - if (controller.activeFilter != - (AppConfig.separateChatTypes - ? ActiveFilter.messages - : ActiveFilter.allChats)) { - controller - .onDestinationSelected(AppConfig.separateChatTypes ? 1 : 0); - return; - } }, child: Row( children: [ if (FluffyThemes.isColumnMode(context) && controller.widget.displayNavigationRail) ...[ - Builder( - builder: (context) { - final allSpaces = - client.rooms.where((room) => room.isSpace); + StreamBuilder( + key: ValueKey( + client.userID.toString(), + ), + stream: client.onSync.stream + .where((s) => s.hasRoomUpdate) + .rateLimit(const Duration(seconds: 1)), + builder: (context, _) { + final allSpaces = Matrix.of(context) + .client + .rooms + .where((room) => room.isSpace); final rootSpaces = allSpaces .where( (space) => !allSpaces.any( @@ -146,58 +69,53 @@ class ChatListView extends StatelessWidget { ), ) .toList(); - final destinations = getNavigationDestinations(context); return SizedBox( width: FluffyThemes.navRailWidth, child: ListView.builder( scrollDirection: Axis.vertical, - itemCount: rootSpaces.length + destinations.length, + itemCount: rootSpaces.length + 2, itemBuilder: (context, i) { - if (i < destinations.length) { + if (i == 0) { return NaviRailItem( - // #Pangea - // isSelected: i == controller.selectedIndex, - isSelected: controller.isSelected(i), - // Pangea# - onTap: () => controller.onDestinationSelected(i), - icon: destinations[i].icon, - selectedIcon: destinations[i].selectedIcon, - toolTip: destinations[i].label, + isSelected: controller.activeSpaceId == null, + onTap: controller.clearActiveSpace, + icon: const Icon(Icons.forum_outlined), + selectedIcon: const Icon(Icons.forum), + toolTip: L10n.of(context)!.chats, + unreadBadgeFilter: (room) => true, ); } - i -= destinations.length; - final isSelected = - controller.activeFilter == ActiveFilter.spaces && - rootSpaces[i].id == controller.activeSpaceId; - //#Pangea - final Room? room = Matrix.of(context) - .client - .getRoomById(rootSpaces[i].id); - // Pangea# + i--; + if (i == rootSpaces.length) { + return NaviRailItem( + isSelected: false, + onTap: () => context.go('/rooms/newspace'), + icon: const Icon(Icons.add), + toolTip: L10n.of(context)!.createNewSpace, + ); + } + final space = rootSpaces[i]; + final displayname = + rootSpaces[i].getLocalizedDisplayname( + MatrixLocals(L10n.of(context)!), + ); + final spaceChildrenIds = + space.spaceChildren.map((c) => c.roomId).toSet(); return NaviRailItem( - toolTip: rootSpaces[i].getLocalizedDisplayname( - MatrixLocals(L10n.of(context)!), - ), - isSelected: isSelected, - // #Pangea - // onTap: () => - // controller.setActiveSpace(rootSpaces[i].id), - onTap: () => chatListHandleSpaceTap( - context, - controller, - rootSpaces[i], - ), - // Pangea# + toolTip: displayname, + isSelected: controller.activeSpaceId == space.id, + onTap: () => + controller.setActiveSpace(rootSpaces[i].id), + unreadBadgeFilter: (room) => + spaceChildrenIds.contains(room.id), icon: Avatar( mxContent: rootSpaces[i].avatar, - name: rootSpaces[i].getLocalizedDisplayname( - MatrixLocals(L10n.of(context)!), - ), + name: displayname, size: 32, - // #Pangea - littleIcon: room?.roomTypeIcon, - // Pangea# + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 4, + ), ), ); }, @@ -217,51 +135,33 @@ class ChatListView extends StatelessWidget { behavior: HitTestBehavior.translucent, child: Scaffold( body: ChatListViewBody(controller), - bottomNavigationBar: controller.displayNavigationBar - ? NavigationBar( - elevation: 4, - labelBehavior: - NavigationDestinationLabelBehavior.alwaysShow, - shadowColor: - Theme.of(context).colorScheme.onSurface, - backgroundColor: - Theme.of(context).colorScheme.surface, - surfaceTintColor: - Theme.of(context).colorScheme.surface, - selectedIndex: controller.selectedIndex, - onDestinationSelected: - controller.onDestinationSelected, - destinations: getNavigationDestinations(context), - ) - : null, - // #Pangea - // floatingActionButton: KeyBoardShortcuts( - // keysToPress: { - // LogicalKeyboardKey.controlLeft, - // LogicalKeyboardKey.keyN, - // }, - // onKeysPressed: () => context.go('/rooms/newprivatechat'), - // helpLabel: L10n.of(context)!.newChat, - // child: selectMode == SelectMode.normal && - // !controller.isSearchMode - // ? StartChatFloatingActionButton( - // activeFilter: controller.activeFilter, - // roomsIsEmpty: false, - // scrolledToTop: controller.scrolledToTop, - // createNewSpace: controller.createNewSpace, - // ) - // : const SizedBox.shrink(), - // ), - floatingActionButton: selectMode == SelectMode.normal - ? StartChatFloatingActionButton( - activeFilter: controller.activeFilter, - roomsIsEmpty: false, - scrolledToTop: controller.scrolledToTop, - controller: controller, - createNewSpace: () {}, - ) - : null, - // Pangea# + floatingActionButton: + // #Pangea + // KeyBoardShortcuts( + // keysToPress: { + // LogicalKeyboardKey.controlLeft, + // LogicalKeyboardKey.keyN, + // }, + // onKeysPressed: () => context.go('/rooms/newprivatechat'), + // helpLabel: L10n.of(context)!.newChat, + // child: + // Pangea# + selectMode == SelectMode.normal && + !controller.isSearchMode && + controller.activeSpaceId == null + ? FloatingActionButton.extended( + // #Pangea + // onPressed: () => + // context.go('/rooms/newprivatechat'), + onPressed: () => context.go('/rooms/newgroup'), + // Pangea# + icon: const Icon(Icons.add_outlined), + label: Text( + L10n.of(context)!.chat, + overflow: TextOverflow.fade, + ), + ) + : const SizedBox.shrink(), ), ), ), diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index 15f52ebe2..0a406fa2c 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -1,5 +1,4 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/utils/find_conversation_partner_dialog.dart'; import 'package:fluffychat/pangea/utils/logout.dart'; import 'package:fluffychat/pangea/utils/space_code.dart'; @@ -32,16 +31,6 @@ class ClientChooserButton extends StatelessWidget { // Pangea# return >[ // #Pangea - // PopupMenuItem( - // value: SettingsAction.newGroup, - // child: Row( - // children: [ - // const Icon(Icons.group_add_outlined), - // const SizedBox(width: 18), - // Text(L10n.of(context)!.createGroup), - // ], - // ), - // ), PopupMenuItem( value: SettingsAction.joinWithClassCode, child: Row( @@ -67,50 +56,44 @@ class ClientChooserButton extends StatelessWidget { // ], // ), // ), - PopupMenuItem( - enabled: matrix.client.rooms.any( - (room) => !room.isSpace && !room.isArchived && !room.isAnalyticsRoom, - ), - value: SettingsAction.myAnalytics, - child: Row( - children: [ - const Icon(Icons.analytics_outlined), - const SizedBox(width: 18), - Expanded(child: Text(L10n.of(context)!.myLearning)), - ], - ), - ), - PopupMenuItem( - value: SettingsAction.newClass, - child: Row( - children: [ - const Icon(Icons.school), - const SizedBox(width: 18), - Expanded(child: Text(L10n.of(context)!.createNewSpace)), - ], - ), - ), // PopupMenuItem( - // value: SettingsAction.newSpace, + // enabled: matrix.client.rooms.any( + // (room) => !room.isSpace && !room.isArchived && !room.isAnalyticsRoom, + // ), + // value: SettingsAction.myAnalytics, // child: Row( // children: [ - // const Icon(Icons.workspaces_outlined), + // const Icon(Icons.analytics_outlined), // const SizedBox(width: 18), - // Text(L10n.of(context)!.createNewSpace), + // Expanded(child: Text(L10n.of(context)!.myLearning)), // ], // ), // ), - // if (controller.pangeaController.permissionsController.isUser18()) - // PopupMenuItem( - // value: SettingsAction.findAConversationPartner, - // child: Row( - // children: [ - // const Icon(Icons.add_circle_outline), - // const SizedBox(width: 18), - // Expanded(child: Text(L10n.of(context)!.findALanguagePartner)), - // ], - // ), + // PopupMenuItem( + // value: SettingsAction.newGroup, + // child: Row( + // children: [ + // const Icon(Icons.group_add_outlined), + // const SizedBox(width: 18), + // Text(L10n.of(context)!.createGroup), + // ], // ), + // ), + // Pangea# + PopupMenuItem( + value: SettingsAction.newSpace, + child: Row( + children: [ + const Icon(Icons.workspaces_outlined), + const SizedBox(width: 18), + // #Pangea + Expanded(child: Text(L10n.of(context)!.createNewSpace)), + // Text(L10n.of(context)!.createNewSpace), + // Pangea# + ], + ), + ), + // #Pangea // PopupMenuItem( // value: SettingsAction.setStatus, // child: Row( @@ -132,19 +115,18 @@ class ClientChooserButton extends StatelessWidget { // ), // ), // Pangea# - PopupMenuItem( + // Currently disabled because of: + // https://github.com/matrix-org/matrix-react-sdk/pull/12286 + /*PopupMenuItem( value: SettingsAction.archive, child: Row( children: [ const Icon(Icons.archive_outlined), const SizedBox(width: 18), - // #Pangea - // Text(L10n.of(context)!.archive), - Expanded(child: Text(L10n.of(context)!.viewArchive)), - // Pangea# + Text(L10n.of(context)!.archive), ], ), - ), + ),*/ // #Pangea PopupMenuItem( value: SettingsAction.learning, @@ -259,7 +241,7 @@ class ClientChooserButton extends StatelessWidget { Widget build(BuildContext context) { final matrix = Matrix.of(context); - int clientCount = 0; + var clientCount = 0; matrix.accountBundles.forEach((key, value) => clientCount += value.length); return FutureBuilder( future: matrix.client.fetchOwnProfile(), @@ -392,21 +374,21 @@ class ClientChooserButton extends StatelessWidget { case SettingsAction.joinWithClassCode: SpaceCodeUtil.joinWithSpaceCodeDialog( context, - controller.pangeaController, + MatrixState.pangeaController, ); break; case SettingsAction.findAConversationPartner: findConversationPartnerDialog( context, - controller.pangeaController, + MatrixState.pangeaController, ); break; // case SettingsAction.spaceAnalytics: // context.go('/rooms/analytics'); // break; - case SettingsAction.myAnalytics: - context.go('/rooms/mylearning'); - break; + // case SettingsAction.myAnalytics: + // context.go('/rooms/mylearning'); + // break; case SettingsAction.logout: pLogoutAction(context); break; @@ -430,7 +412,7 @@ class ClientChooserButton extends StatelessWidget { ); // beginning from end if negative if (index < 0) { - int clientCount = 0; + var clientCount = 0; matrix.accountBundles .forEach((key, value) => clientCount += value.length); _handleKeyboardShortcut(matrix, clientCount, context); @@ -450,7 +432,7 @@ class ClientChooserButton extends StatelessWidget { } int? _shortcutIndexOfClient(MatrixState matrix, Client client) { - int index = 0; + var index = 0; final bundles = matrix.accountBundles.keys.toList() ..sort( @@ -497,7 +479,7 @@ enum SettingsAction { learning, joinWithClassCode, // spaceAnalytics, - myAnalytics, + // myAnalytics, findAConversationPartner, logout, newClass, diff --git a/lib/pages/chat_list/dummy_chat_list_item.dart b/lib/pages/chat_list/dummy_chat_list_item.dart new file mode 100644 index 000000000..8652cccd1 --- /dev/null +++ b/lib/pages/chat_list/dummy_chat_list_item.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; + +class DummyChatListItem extends StatelessWidget { + final double opacity; + final bool animate; + + const DummyChatListItem({ + required this.opacity, + required this.animate, + super.key, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final titleColor = theme.textTheme.bodyLarge!.color!.withAlpha(100); + final subtitleColor = theme.textTheme.bodyLarge!.color!.withAlpha(50); + return Opacity( + opacity: opacity, + child: ListTile( + leading: CircleAvatar( + backgroundColor: titleColor, + child: animate + ? CircularProgressIndicator( + strokeWidth: 1, + color: theme.textTheme.bodyLarge!.color, + ) + : const SizedBox.shrink(), + ), + title: Row( + children: [ + Expanded( + child: Container( + height: 14, + decoration: BoxDecoration( + color: titleColor, + borderRadius: BorderRadius.circular(3), + ), + ), + ), + const SizedBox(width: 36), + Container( + height: 14, + width: 14, + decoration: BoxDecoration( + color: subtitleColor, + borderRadius: BorderRadius.circular(14), + ), + ), + const SizedBox(width: 12), + Container( + height: 14, + width: 14, + decoration: BoxDecoration( + color: subtitleColor, + borderRadius: BorderRadius.circular(14), + ), + ), + ], + ), + subtitle: Container( + decoration: BoxDecoration( + color: subtitleColor, + borderRadius: BorderRadius.circular(3), + ), + height: 12, + margin: const EdgeInsets.only(right: 22), + ), + ), + ); + } +} diff --git a/lib/pages/chat_list/nav_rail_item.dart b/lib/pages/chat_list/nav_rail_item.dart new file mode 100644 index 000000000..6264b0b18 --- /dev/null +++ b/lib/pages/chat_list/nav_rail_item.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; + +import 'package:fluffychat/config/app_config.dart'; +import '../../config/themes.dart'; + +class NaviRailItem extends StatefulWidget { + final String toolTip; + final bool isSelected; + final void Function() onTap; + final Widget icon; + final Widget? selectedIcon; + + const NaviRailItem({ + required this.toolTip, + required this.isSelected, + required this.onTap, + required this.icon, + this.selectedIcon, + super.key, + }); + + @override + State createState() => _NaviRailItemState(); +} + +class _NaviRailItemState extends State { + bool _hovered = false; + + void _onHover(bool hover) { + if (hover == _hovered) return; + setState(() { + _hovered = hover; + }); + } + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + final borderRadius = BorderRadius.circular(AppConfig.borderRadius); + return SizedBox( + height: 64, + width: 64, + child: Stack( + children: [ + Positioned( + top: 16, + bottom: 16, + left: 0, + child: AnimatedContainer( + width: widget.isSelected ? 4 : 0, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + decoration: BoxDecoration( + color: theme.colorScheme.primary, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(90), + bottomRight: Radius.circular(90), + ), + ), + ), + ), + Center( + child: AnimatedScale( + scale: _hovered ? 1.2 : 1.0, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + child: Material( + borderRadius: borderRadius, + color: widget.isSelected + ? theme.colorScheme.primaryContainer + : theme.colorScheme.surface, + child: Tooltip( + message: widget.toolTip, + child: InkWell( + borderRadius: borderRadius, + onTap: widget.onTap, + onHover: _onHover, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 8.0, + ), + child: widget.isSelected + ? widget.selectedIcon ?? widget.icon + : widget.icon, + ), + ), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/chat_list/navi_rail_item.dart b/lib/pages/chat_list/navi_rail_item.dart index d09659f88..77837bfef 100644 --- a/lib/pages/chat_list/navi_rail_item.dart +++ b/lib/pages/chat_list/navi_rail_item.dart @@ -1,14 +1,20 @@ import 'package:flutter/material.dart'; +import 'package:badges/badges.dart'; +import 'package:matrix/matrix.dart'; + import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/widgets/hover_builder.dart'; +import 'package:fluffychat/widgets/unread_rooms_badge.dart'; import '../../config/themes.dart'; -class NaviRailItem extends StatefulWidget { +class NaviRailItem extends StatelessWidget { final String toolTip; final bool isSelected; final void Function() onTap; final Widget icon; final Widget? selectedIcon; + final bool Function(Room)? unreadBadgeFilter; const NaviRailItem({ required this.toolTip, @@ -16,80 +22,80 @@ class NaviRailItem extends StatefulWidget { required this.onTap, required this.icon, this.selectedIcon, + this.unreadBadgeFilter, super.key, }); - - @override - State createState() => _NaviRailItemState(); -} - -class _NaviRailItemState extends State { - bool _hovered = false; - - void _onHover(bool hover) { - if (hover == _hovered) return; - setState(() { - _hovered = hover; - }); - } - @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final borderRadius = BorderRadius.circular(AppConfig.borderRadius); - return SizedBox( - height: 64, - width: 64, - child: Stack( - children: [ - Positioned( - top: 16, - bottom: 16, - left: 0, - child: AnimatedContainer( - width: widget.isSelected ? 4 : 0, - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary, - borderRadius: const BorderRadius.only( - topRight: Radius.circular(90), - bottomRight: Radius.circular(90), - ), - ), - ), - ), - Center( - child: AnimatedScale( - scale: _hovered ? 1.2 : 1.0, - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - child: Material( - borderRadius: borderRadius, - color: widget.isSelected - ? Theme.of(context).colorScheme.primaryContainer - : Theme.of(context).colorScheme.surface, - child: Tooltip( - message: widget.toolTip, - child: InkWell( - borderRadius: borderRadius, - onTap: widget.onTap, - onHover: _onHover, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 8.0, - ), - child: widget.isSelected - ? widget.selectedIcon ?? widget.icon - : widget.icon, + final icon = isSelected ? selectedIcon ?? this.icon : this.icon; + final unreadBadgeFilter = this.unreadBadgeFilter; + return HoverBuilder( + builder: (context, hovered) { + return SizedBox( + height: FluffyThemes.navRailWidth, + width: FluffyThemes.navRailWidth, + child: Stack( + children: [ + Positioned( + top: 16, + bottom: 16, + left: 0, + child: AnimatedContainer( + width: isSelected ? 4 : 0, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + decoration: BoxDecoration( + color: theme.colorScheme.primary, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(90), + bottomRight: Radius.circular(90), ), ), ), ), - ), + Center( + child: AnimatedScale( + scale: hovered ? 1.2 : 1.0, + duration: FluffyThemes.animationDuration, + curve: FluffyThemes.animationCurve, + child: Material( + borderRadius: borderRadius, + color: isSelected + ? theme.colorScheme.primaryContainer + : theme.colorScheme.surface, + child: Tooltip( + message: toolTip, + child: InkWell( + borderRadius: borderRadius, + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 8.0, + ), + child: unreadBadgeFilter == null + ? icon + : UnreadRoomsBadge( + filter: unreadBadgeFilter, + badgePosition: BadgePosition.topEnd( + top: -12, + end: -8, + ), + child: icon, + ), + ), + ), + ), + ), + ), + ), + ], ), - ], - ), + ); + }, ); } } diff --git a/lib/pages/chat_list/search_title.dart b/lib/pages/chat_list/search_title.dart index 62bcfb684..496a5feec 100644 --- a/lib/pages/chat_list/search_title.dart +++ b/lib/pages/chat_list/search_title.dart @@ -17,55 +17,59 @@ class SearchTitle extends StatelessWidget { }); @override - Widget build(BuildContext context) => Material( - shape: Border( - top: BorderSide( - color: Theme.of(context).dividerColor, - width: 1, - ), - bottom: BorderSide( - color: Theme.of(context).dividerColor, - width: 1, - ), + Widget build(BuildContext context) { + final theme = Theme.of(context); + + return Material( + shape: Border( + top: BorderSide( + color: theme.dividerColor, + width: 1, ), - color: color ?? Theme.of(context).colorScheme.surface, - child: InkWell( - onTap: onTap, - splashColor: Theme.of(context).colorScheme.surface, - child: Align( - alignment: Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: IconTheme( - data: Theme.of(context).iconTheme.copyWith(size: 16), - child: Row( - children: [ - icon, - const SizedBox(width: 16), - Text( - title, - textAlign: TextAlign.left, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, - fontSize: 12, - fontWeight: FontWeight.bold, + bottom: BorderSide( + color: theme.dividerColor, + width: 1, + ), + ), + color: color ?? theme.colorScheme.surface, + child: InkWell( + onTap: onTap, + splashColor: theme.colorScheme.surface, + child: Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + child: IconTheme( + data: theme.iconTheme.copyWith(size: 16), + child: Row( + children: [ + icon, + const SizedBox(width: 16), + Text( + title, + textAlign: TextAlign.left, + style: TextStyle( + color: theme.colorScheme.onSurface, + fontSize: 12, + fontWeight: FontWeight.bold, + ), + ), + if (trailing != null) + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: trailing!, ), ), - if (trailing != null) - Expanded( - child: Align( - alignment: Alignment.centerRight, - child: trailing!, - ), - ), - ], - ), + ], ), ), ), ), - ); + ), + ); + } } diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index a90c0d094..589c0341c 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -2,19 +2,18 @@ import 'dart:async'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:collection/collection.dart'; -import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; +import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart'; -import 'package:fluffychat/pages/chat_list/utils/on_chat_tap.dart'; -import 'package:fluffychat/pangea/constants/class_default_values.dart'; import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/utils/chat_list_handle_space_tap.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:fluffychat/pangea/widgets/chat_list/chat_list_header_wrapper.dart'; -import 'package:fluffychat/pangea/widgets/chat_list/chat_list_item_wrapper.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; +import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; +import 'package:fluffychat/utils/localized_exception_extension.dart'; +import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/avatar.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:fluffychat/widgets/public_room_bottom_sheet.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; @@ -22,16 +21,30 @@ import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart'; -import '../../utils/localized_exception_extension.dart'; -import '../../widgets/matrix.dart'; +enum AddRoomType { chat, subspace } class SpaceView extends StatefulWidget { + final String spaceId; + final void Function() onBack; + final void Function(String spaceId) toParentSpace; + final void Function(Room room) onChatTab; + final void Function(Room room, BuildContext context) onChatContext; + final String? activeChat; + // #Pangea final ChatListController controller; - final ScrollController scrollController; - const SpaceView( - this.controller, { + // Pangea# + + const SpaceView({ + required this.spaceId, + required this.onBack, + required this.onChatTab, + required this.activeChat, + required this.toParentSpace, + required this.onChatContext, + // #Pangea + required this.controller, + // Pangea# super.key, - required this.scrollController, }); @override @@ -39,40 +52,15 @@ class SpaceView extends StatefulWidget { } class _SpaceViewState extends State { - static final Map _lastResponse = {}; - - String? prevBatch; - Object? error; - bool loading = false; // #Pangea - bool refreshing = false; + // final List _discoveredChildren = []; + List? _discoveredChildren; StreamSubscription? _roomSubscription; - - final String _chatCountsKey = 'chatCounts'; - Map get chatCounts => Map.from( - widget.controller.pangeaController.pStoreService.read(_chatCountsKey) ?? - {}, - ); - - /// Used to filter out sync updates with hierarchy updates for the active - /// space so that the view can be auto-reloaded in the room subscription - bool hasHierarchyUpdate(SyncUpdate update) { - final joinTimeline = - update.rooms?.join?[widget.controller.activeSpaceId]?.timeline; - final leaveTimeline = - update.rooms?.leave?[widget.controller.activeSpaceId]?.timeline; - if (joinTimeline == null && leaveTimeline == null) return false; - final bool hasJoinUpdate = joinTimeline?.events?.any( - (event) => event.type == EventTypes.SpaceChild, - ) ?? - false; - final bool hasLeaveUpdate = leaveTimeline?.events?.any( - (event) => event.type == EventTypes.SpaceChild, - ) ?? - false; - return hasJoinUpdate || hasLeaveUpdate; - } // Pangea# + final TextEditingController _filterController = TextEditingController(); + String? _nextBatch; + bool _noMoreRooms = false; + bool _isLoading = false; @override void initState() { @@ -82,7 +70,7 @@ class _SpaceViewState extends State { // If, on launch, this room has had updates to its children, // ensure the hierarchy is properly reloaded final bool hasUpdate = widget.controller.hasUpdates.contains( - widget.controller.activeSpaceId, + widget.spaceId, ); loadHierarchy(hasUpdate: hasUpdate).then( @@ -92,8 +80,6 @@ class _SpaceViewState extends State { ), ); - loadChatCounts(); - // Listen for changes to the activeSpace's hierarchy, // and reload the hierarchy when they come through final client = Matrix.of(context).client; @@ -105,132 +91,77 @@ class _SpaceViewState extends State { } // #Pangea + @override + void didUpdateWidget(covariant SpaceView oldWidget) { + // initState doesn't re-run when navigating between spaces + // via the navigation rail, so this accounts for that + super.didUpdateWidget(oldWidget); + if (oldWidget.spaceId != widget.spaceId) { + _discoveredChildren = null; + _nextBatch = null; + _noMoreRooms = false; + + loadHierarchy(hasUpdate: true).then( + // remove this space ID from the set of space IDs with updates + (_) { + if (widget.controller.hasUpdates.contains(widget.spaceId)) { + widget.controller.hasUpdates.remove( + widget.controller.activeSpaceId, + ); + } + }); + } + } + @override void dispose() { _roomSubscription?.cancel(); super.dispose(); } - // Pangea# - void _refresh() { - // #Pangea - // _lastResponse.remove(widget.controller.activseSpaceId); - // loadHierarchy(); - if (mounted) setState(() => refreshing = true); - loadHierarchy(hasUpdate: true).whenComplete(() { - if (mounted) setState(() => refreshing = false); + Future loadHierarchy({hasUpdate = false}) async { + final room = Matrix.of(context).client.getRoomById(widget.spaceId); + if (room == null) return; + + setState(() { + _isLoading = true; }); - // Pangea# - } - - // #Pangea - // Future loadHierarchy([String? prevBatch]) async { - // final activeSpaceId = widget.controller.activeSpaceId; - // if (activeSpaceId == null) return null; - // final client = Matrix.of(context).client; - - // final activeSpace = client.getRoomById(activeSpaceId); - // await activeSpace?.postLoad(); - - // setState(() { - // error = null; - // loading = true; - // }); - - // try { - // final response = await client.getSpaceHierarchy( - // activeSpaceId, - // maxDepth: 1, - // from: prevBatch, - // ); - - // if (prevBatch != null) { - // response.rooms.insertAll(0, _lastResponse[activeSpaceId]?.rooms ?? []); - // } - // setState(() { - // _lastResponse[activeSpaceId] = response; - // }); - // return _lastResponse[activeSpaceId]!; - // } catch (e) { - // setState(() { - // error = e; - // }); - // rethrow; - // } finally { - // setState(() { - // loading = false; - // }); - // } - // } - - /// Loads the hierarchy of the active space (or the given spaceId) and stores - /// it in _lastResponse map. If there's already a response in that map for the - /// spaceId, it will try to load the next batch and add the new rooms to the - /// already loaded ones. Displays a loading indicator while loading, and an error - /// message if an error occurs. - /// If hasUpdate is true, it will force the hierarchy to be reloaded. - Future loadHierarchy({ - String? spaceId, - bool hasUpdate = false, - }) async { - if ((widget.controller.activeSpaceId == null && spaceId == null) || - loading) { - return; - } - - loading = true; - error = null; - setState(() {}); try { - await _loadHierarchy(spaceId: spaceId, hasUpdate: hasUpdate); + await _loadHierarchy(activeSpace: room, hasUpdate: hasUpdate); } catch (e, s) { - if (mounted) { - setState(() => error = e); - } - ErrorHandler.logError(e: e, s: s); + Logs().w('Unable to load hierarchy', e, s); + if (!mounted) return; + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } finally { - if (mounted) { - setState(() => loading = false); - } + setState(() { + _isLoading = false; + }); } } /// Internal logic of loadHierarchy. It will load the hierarchy of /// the active space id (or specified spaceId). Future _loadHierarchy({ - String? spaceId, + required Room activeSpace, bool hasUpdate = false, }) async { - final client = Matrix.of(context).client; - final activeSpaceId = (widget.controller.activeSpaceId ?? spaceId)!; - final activeSpace = client.getRoomById(activeSpaceId); - - if (activeSpace == null) { - ErrorHandler.logError( - e: Exception('Space not found in loadHierarchy'), - data: {'spaceId': activeSpaceId}, - ); - return; - } - // Load all of the space's state events. Space Child events // are used to filtering out unsuggested, unjoined rooms. await activeSpace.postLoad(); // The current number of rooms loaded for this space that are visible in the UI - final int prevLength = _lastResponse[activeSpaceId] != null && !hasUpdate - ? filterHierarchyResponse( - activeSpace, - _lastResponse[activeSpaceId]!.rooms, - ).length - : 0; + final int prevLength = !hasUpdate ? (_discoveredChildren?.length ?? 0) : 0; // Failsafe to prevent too many calls to the server in a row int callsToServer = 0; - GetSpaceHierarchyResponse? currentHierarchy = - hasUpdate ? null : _lastResponse[activeSpaceId]; + List? currentHierarchy = + _discoveredChildren == null || hasUpdate + ? null + : List.from(_discoveredChildren!); + String? currentNextBatch = hasUpdate ? null : _nextBatch; // Makes repeated calls to the server until 10 new visible rooms have // been loaded, or there are no rooms left to load. Using a loop here, @@ -240,268 +171,144 @@ class _SpaceViewState extends State { // coming through from those calls are analytics rooms). while (callsToServer < 5) { // if this space has been loaded and there are no more rooms to load, break - if (currentHierarchy != null && currentHierarchy.nextBatch == null) { + if (currentHierarchy != null && currentNextBatch == null) { break; } // if this space has been loaded and 10 new rooms have been loaded, break - if (currentHierarchy != null) { - final int currentLength = filterHierarchyResponse( - activeSpace, - currentHierarchy.rooms, - ).length; - - if (currentLength - prevLength >= 10) { - break; - } + final int currentLength = currentHierarchy?.length ?? 0; + if (currentLength - prevLength >= 10) { + break; } // make the call to the server - final response = await client.getSpaceHierarchy( - activeSpaceId, - maxDepth: 1, - from: currentHierarchy?.nextBatch, - limit: 100, - ); + final response = await Matrix.of(context).client.getSpaceHierarchy( + widget.spaceId, + maxDepth: 1, + from: currentNextBatch, + limit: 100, + ); callsToServer++; + if (response.nextBatch == null) { + _noMoreRooms = true; + } + // if rooms have earlier been loaded for this space, add those // previously loaded rooms to the front of the response list - if (currentHierarchy != null) { - response.rooms.insertAll( - 0, - currentHierarchy.rooms, - ); - } + response.rooms.insertAll( + 0, + currentHierarchy ?? [], + ); // finally, set the response to the last response for this space - currentHierarchy = response; + // and set the current next batch token + currentHierarchy = filterHierarchyResponse(activeSpace, response.rooms); + currentNextBatch = response.nextBatch; } - if (currentHierarchy != null) { - _lastResponse[activeSpaceId] = currentHierarchy; - } - - // After making those calls to the server, set the chat count for - // this space. Used for the UI of the 'All Spaces' view - setChatCount( - activeSpace, - _lastResponse[activeSpaceId] ?? - GetSpaceHierarchyResponse( - rooms: [], - ), - ); + _discoveredChildren = currentHierarchy; + _discoveredChildren?.sort(sortSpaceChildren); + _nextBatch = currentNextBatch; } + + // void _loadHierarchy() async { + // final room = Matrix.of(context).client.getRoomById(widget.spaceId); + // if (room == null) return; + + // setState(() { + // _isLoading = true; + // }); + + // try { + // final hierarchy = await room.client.getSpaceHierarchy( + // widget.spaceId, + // suggestedOnly: false, + // maxDepth: 2, + // from: _nextBatch, + // ); + // if (!mounted) return; + // setState(() { + // _nextBatch = hierarchy.nextBatch; + // if (hierarchy.nextBatch == null) { + // _noMoreRooms = true; + // } + // _discoveredChildren.addAll( + // hierarchy.rooms + // .where((c) => room.client.getRoomById(c.roomId) == null), + // ); + // _isLoading = false; + // }); + // } catch (e, s) { + // Logs().w('Unable to load hierarchy', e, s); + // if (!mounted) return; + // ScaffoldMessenger.of(context) + // .showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); + // setState(() { + // _isLoading = false; + // }); + // } + // } // Pangea# - void _onJoinSpaceChild(SpaceRoomsChunk spaceChild) async { + void _joinChildRoom(SpaceRoomsChunk item) async { final client = Matrix.of(context).client; - final space = client.getRoomById(widget.controller.activeSpaceId!); - if (client.getRoomById(spaceChild.roomId) == null) { - final result = await showFutureLoadingDialog( - context: context, - future: () async { - await client.joinRoom( - spaceChild.roomId, - serverName: space?.spaceChildren - .firstWhereOrNull( - (child) => child.roomId == spaceChild.roomId, - ) - ?.via, - ); - if (client.getRoomById(spaceChild.roomId) == null) { - // Wait for room actually appears in sync - await client.waitForRoomInSync(spaceChild.roomId, join: true); - } - // #Pangea - final room = client.getRoomById(spaceChild.roomId); - if (room != null && (await room.leaveIfFull())) { - throw L10n.of(context)!.roomFull; - } - // Pangea# - }, - ); - if (result.error != null) return; - _refresh(); + final space = client.getRoomById(widget.spaceId); + + final joined = await showAdaptiveBottomSheet( + context: context, + builder: (_) => PublicRoomBottomSheet( + outerContext: context, + chunk: item, + via: space?.spaceChildren + .firstWhereOrNull( + (child) => child.roomId == item.roomId, + ) + ?.via, + ), + ); + if (mounted && joined == true) { + setState(() { + _discoveredChildren?.remove(item); + }); } - // #Pangea - else { - final room = client.getRoomById(spaceChild.roomId)!; - if (room.membership != Membership.leave) return; - final joinResult = await showFutureLoadingDialog( - context: context, - future: () async { - final waitForRoom = room.client.waitForRoomInSync( - room.id, - join: true, - ); - await room.join(); - await waitForRoom; - if (await room.leaveIfFull()) { - throw L10n.of(context)!.roomFull; - } - }, - ); - if (joinResult.error != null) return; - } - // Pangea# - if (spaceChild.roomType == 'm.space') { - if (spaceChild.roomId == widget.controller.activeSpaceId) { - // #Pangea - // context.go('/rooms/${spaceChild.roomId}'); - context.go('/rooms/${spaceChild.roomId}/details'); - // Pangea# - } else { - widget.controller.setActiveSpace(spaceChild.roomId); - } - return; - } - context.go('/rooms/${spaceChild.roomId}'); } - void _onSpaceChildContextMenu([ - SpaceRoomsChunk? spaceChild, - Room? room, - ]) async { - final client = Matrix.of(context).client; - final activeSpaceId = widget.controller.activeSpaceId; - final activeSpace = - activeSpaceId == null ? null : client.getRoomById(activeSpaceId); - final action = await showModalActionSheet( - context: context, - title: spaceChild?.name ?? - room?.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)!), - ), - // #Pangea - // message: spaceChild?.topic ?? room?.topic, - // Pangea# - actions: [ - // #Pangea - // if (room == null) - if (room == null || room.membership == Membership.leave) - // Pangea# - SheetAction( - key: SpaceChildContextAction.join, - label: L10n.of(context)!.joinRoom, - icon: Icons.send_outlined, - ), - if (spaceChild != null && - // #Pangea - room != null && - room.ownPowerLevel >= ClassDefaultValues.powerLevelOfAdmin && - // Pangea# - (activeSpace?.canChangeStateEvent(EventTypes.SpaceChild) ?? false)) - SheetAction( - key: SpaceChildContextAction.removeFromSpace, - label: L10n.of(context)!.removeFromSpace, - icon: Icons.delete_sweep_outlined, - ), - // #Pangea - if (room != null && - room.ownPowerLevel >= ClassDefaultValues.powerLevelOfAdmin) - SheetAction( - key: SpaceChildContextAction.addToSpace, - label: L10n.of(context)!.addToSpace, - icon: Icons.workspaces_outlined, - ), - if (room != null && - room.isRoomAdmin && - room.membership != Membership.leave) - SheetAction( - key: SpaceChildContextAction.archive, - label: room.isSpace - ? L10n.of(context)!.archiveSpace - : L10n.of(context)!.archive, - icon: Icons.architecture_outlined, - isDestructiveAction: true, - ), - // if (room != null) - if (room != null && room.membership != Membership.leave) - // Pangea# - SheetAction( - key: SpaceChildContextAction.leave, - label: L10n.of(context)!.leave, - // #Pangea - // icon: Icons.delete_outlined, - icon: Icons.arrow_forward, - // Pangea# - isDestructiveAction: true, - ), - ], - ); - if (action == null) return; + void _onSpaceAction(SpaceActions action) async { + final space = Matrix.of(context).client.getRoomById(widget.spaceId); switch (action) { - case SpaceChildContextAction.join: - _onJoinSpaceChild(spaceChild!); + case SpaceActions.settings: + await space?.postLoad(); + context.push('/rooms/${widget.spaceId}/details'); break; - case SpaceChildContextAction.leave: - // #Pangea - widget.controller.cancelAction(); - if (room == null) return; - if (room.isSpace) { - await room.isOnlyAdmin() - ? await room.archiveSpace( - context, - Matrix.of(context).client, - onlyAdmin: true, - ) - : await room.leaveSpace( - context, - Matrix.of(context).client, - ); - } else { - widget.controller.toggleSelection(room.id); - await widget.controller.leaveAction(); - } - _refresh(); + case SpaceActions.invite: + await space?.postLoad(); + context.push('/rooms/${widget.spaceId}/invite'); break; - // await showFutureLoadingDialog( - // context: context, - // future: room!.leave, - // ); - // break; - // Pangea# - case SpaceChildContextAction.removeFromSpace: - await showFutureLoadingDialog( + case SpaceActions.leave: + final confirmed = await showOkCancelAlertDialog( + useRootNavigator: false, context: context, - future: () => activeSpace!.removeSpaceChild(spaceChild!.roomId), + title: L10n.of(context)!.areYouSure, + okLabel: L10n.of(context)!.ok, + cancelLabel: L10n.of(context)!.cancel, + message: L10n.of(context)!.archiveRoomDescription, ); - break; - // #Pangea - case SpaceChildContextAction.archive: - widget.controller.cancelAction(); - // #Pangea - if (room == null || room.membership == Membership.leave) return; - if (room.isSpace) { - await room.archiveSpace( - context, - Matrix.of(context).client, - onlyAdmin: false, - ); - } else { - widget.controller.toggleSelection(room.id); - await widget.controller.archiveAction(); - } - // Pangea# - _refresh(); - break; - case SpaceChildContextAction.addToSpace: - widget.controller.cancelAction(); - // #Pangea - if (room == null || room.membership == Membership.leave) return; - // Pangea# - widget.controller.toggleSelection(room.id); - await widget.controller.addToSpace(); - // #Pangea - setState(() => widget.controller.selectedRoomIds.clear()); - // Pangea# - break; + if (!mounted) return; + if (confirmed != OkCancelResult.ok) return; + + final success = await showFutureLoadingDialog( + context: context, + future: () async => await space?.leave(), + ); + if (!mounted) return; + if (success.error != null) return; + widget.onBack(); } } - void _addChatOrSubSpace() async { + void _addChatOrSubspace() async { final roomType = await showConfirmationDialog( context: context, title: L10n.of(context)!.addChatOrSubSpace, @@ -512,7 +319,10 @@ class _SpaceViewState extends State { ), AlertDialogAction( key: AddRoomType.chat, - label: L10n.of(context)!.createGroup, + // #Pangea + // label: L10n.of(context)!.createGroup, + label: L10n.of(context)!.createChat, + // Pangea# ), ], ); @@ -522,12 +332,18 @@ class _SpaceViewState extends State { context: context, title: roomType == AddRoomType.subspace ? L10n.of(context)!.createNewSpace - : L10n.of(context)!.createGroup, + // #Pangea + // : L10n.of(context)!.createGroup, + : L10n.of(context)!.createChat, + // Pangea# textFields: [ DialogTextField( hintText: roomType == AddRoomType.subspace ? L10n.of(context)!.spaceName - : L10n.of(context)!.groupName, + // #Pangea + // : L10n.of(context)!.groupName, + : L10n.of(context)!.chatName, + // Pangea# minLines: 1, maxLines: 1, maxLength: 64, @@ -554,9 +370,8 @@ class _SpaceViewState extends State { context: context, future: () async { late final String roomId; - final activeSpace = client.getRoomById( - widget.controller.activeSpaceId!, - )!; + final activeSpace = client.getRoomById(widget.spaceId)!; + await activeSpace.postLoad(); if (roomType == AddRoomType.subspace) { roomId = await client.createSpace( @@ -569,50 +384,29 @@ class _SpaceViewState extends State { } else { roomId = await client.createGroupChat( groupName: names.first, + preset: activeSpace.joinRules == JoinRules.public + ? CreateRoomPreset.publicChat + : CreateRoomPreset.privateChat, + visibility: activeSpace.joinRules == JoinRules.public + ? sdk.Visibility.public + : sdk.Visibility.private, initialState: names.length > 1 && names.last.isNotEmpty ? [ - sdk.StateEvent( - type: sdk.EventTypes.RoomTopic, + StateEvent( + type: EventTypes.RoomTopic, content: {'topic': names.last}, ), ] : null, ); } - await activeSpace.setSpaceChild( - roomId, - // #Pangea - suggested: true, - // Pangea# - ); + await activeSpace.setSpaceChild(roomId); }, ); if (result.error != null) return; - _refresh(); } // #Pangea - Future loadChatCounts() async { - // if not in the call spaces view, don't load chat count yet - if (widget.controller.activeSpaceId != null) return; - - final List allSpaces = - Matrix.of(context).client.rooms.where((room) => room.isSpace).toList(); - - for (final Room space in allSpaces) { - // check if the space is visible in the all spaces list - final bool isRootSpace = !allSpaces.any( - (parentSpace) => - parentSpace.spaceChildren.any((child) => child.roomId == space.id), - ); - - // if it's visible, and it hasn't been loaded yet, load chat count - if (isRootSpace && !chatCounts.containsKey(space.id)) { - loadHierarchy(spaceId: space.id); - } - } - } - bool includeSpaceChild( Room space, SpaceRoomsChunk hierarchyMember, @@ -637,6 +431,11 @@ class _SpaceViewState extends State { ) { final List filteredChildren = []; for (final child in hierarchyResponse) { + if (child.roomId == widget.spaceId || + Matrix.of(context).client.getRoomById(child.roomId) != null) { + continue; + } + final isDuplicate = filteredChildren.any( (filtered) => filtered.roomId == child.roomId, ); @@ -649,6 +448,23 @@ class _SpaceViewState extends State { return filteredChildren; } + /// Used to filter out sync updates with hierarchy updates for the active + /// space so that the view can be auto-reloaded in the room subscription + bool hasHierarchyUpdate(SyncUpdate update) { + final joinTimeline = update.rooms?.join?[widget.spaceId]?.timeline; + final leaveTimeline = update.rooms?.leave?[widget.spaceId]?.timeline; + if (joinTimeline == null && leaveTimeline == null) return false; + final bool hasJoinUpdate = joinTimeline?.events?.any( + (event) => event.type == EventTypes.SpaceChild, + ) ?? + false; + final bool hasLeaveUpdate = leaveTimeline?.events?.any( + (event) => event.type == EventTypes.SpaceChild, + ) ?? + false; + return hasJoinUpdate || hasLeaveUpdate; + } + int sortSpaceChildren( SpaceRoomsChunk a, SpaceRoomsChunk b, @@ -663,454 +479,357 @@ class _SpaceViewState extends State { } return 0; } - - Future setChatCount( - Room space, - GetSpaceHierarchyResponse? response, - ) async { - final Map updatedChatCounts = Map.from(chatCounts); - final List spaceChildren = response?.rooms ?? []; - final filteredChildren = filterHierarchyResponse(space, spaceChildren) - .where((sc) => sc.roomId != space.id) - .toList(); - updatedChatCounts[space.id] = filteredChildren.length; - - await widget.controller.pangeaController.pStoreService.save( - _chatCountsKey, - updatedChatCounts, - ); - } - - bool roomCountLoading(Room space) => - space.membership == Membership.join && !chatCounts.containsKey(space.id); - - Widget spaceSubtitle(Room space) { - if (roomCountLoading(space)) { - return const CircularProgressIndicator.adaptive(); - } - - return Text( - space.membership == Membership.join - ? L10n.of(context)!.numChats( - chatCounts[space.id].toString(), - ) - : L10n.of(context)!.youreInvited, - ); - } // Pangea# @override Widget build(BuildContext context) { - final client = Matrix.of(context).client; - final activeSpaceId = widget.controller.activeSpaceId; - final activeSpace = activeSpaceId == null - ? null - : client.getRoomById( - activeSpaceId, - ); - final allSpaces = client.rooms.where((room) => room.isSpace); - if (activeSpaceId == null) { - final rootSpaces = allSpaces - .where( - (space) => - !allSpaces.any( - (parentSpace) => parentSpace.spaceChildren - .any((child) => child.roomId == space.id), - ) && - space - .getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)) - .toLowerCase() - .contains( - widget.controller.searchController.text.toLowerCase(), - ), - ) - .toList(); + final theme = Theme.of(context); - return SafeArea( - child: CustomScrollView( - controller: widget.scrollController, - slivers: [ - // #Pangea - // ChatListHeader(controller: widget.controller), - ChatListHeaderWrapper(controller: widget.controller), - // Pangea# - SliverList( - delegate: SliverChildBuilderDelegate( - (context, i) { - final rootSpace = rootSpaces[i]; - final displayname = rootSpace.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)!), - ); - return Material( - color: Theme.of(context).colorScheme.surface, - child: ListTile( - leading: Avatar( - mxContent: rootSpace.avatar, - name: displayname, - // #Pangea - littleIcon: rootSpace.roomTypeIcon, - // Pangea# + final room = Matrix.of(context).client.getRoomById(widget.spaceId); + final displayname = + room?.getLocalizedDisplayname() ?? L10n.of(context)!.nothingFound; + return Scaffold( + appBar: AppBar( + leading: Center( + child: CloseButton( + onPressed: widget.onBack, + ), + ), + titleSpacing: 0, + title: ListTile( + contentPadding: EdgeInsets.zero, + leading: Avatar( + mxContent: room?.avatar, + name: displayname, + borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), + ), + title: Text( + displayname, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + subtitle: room == null + ? null + : Text( + L10n.of(context)!.countChatsAndCountParticipants( + room.spaceChildren.length, + room.summary.mJoinedMemberCount ?? 1, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + actions: [ + PopupMenuButton( + onSelected: _onSpaceAction, + itemBuilder: (context) => [ + PopupMenuItem( + value: SpaceActions.settings, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.settings_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.settings), + ], + ), + ), + PopupMenuItem( + value: SpaceActions.invite, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.person_add_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.invite), + ], + ), + ), + PopupMenuItem( + value: SpaceActions.leave, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Icon(Icons.delete_outlined), + const SizedBox(width: 12), + Text(L10n.of(context)!.leave), + ], + ), + ), + ], + ), + ], + ), + body: room == null + ? const Center( + child: Icon( + Icons.search_outlined, + size: 80, + ), + ) + : StreamBuilder( + stream: room.client.onSync.stream + .where((s) => s.hasRoomUpdate) + .rateLimit(const Duration(seconds: 1)), + builder: (context, snapshot) { + final childrenIds = room.spaceChildren + .map((c) => c.roomId) + .whereType() + .toSet(); + + final joinedRooms = room.client.rooms + .where((room) => childrenIds.remove(room.id)) + // #Pangea + .where((room) => !room.isAnalyticsRoom) + // Pangea# + .toList(); + + final joinedParents = room.spaceParents + .map((parent) { + final roomId = parent.roomId; + if (roomId == null) return null; + return room.client.getRoomById(roomId); + }) + .whereType() + .toList(); + final filter = _filterController.text.trim().toLowerCase(); + return CustomScrollView( + slivers: [ + SliverAppBar( + floating: true, + toolbarHeight: 72, + scrolledUnderElevation: 0, + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + title: TextField( + controller: _filterController, + onChanged: (_) => setState(() {}), + textInputAction: TextInputAction.search, + decoration: InputDecoration( + filled: true, + fillColor: theme.colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(99), + ), + contentPadding: EdgeInsets.zero, + hintText: L10n.of(context)!.search, + hintStyle: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontWeight: FontWeight.normal, + ), + floatingLabelBehavior: FloatingLabelBehavior.never, + prefixIcon: IconButton( + onPressed: () {}, + icon: Icon( + Icons.search_outlined, + color: theme.colorScheme.onPrimaryContainer, + ), + ), + ), ), - title: Text( - displayname, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - // #Pangea - subtitle: Row( - children: [ - spaceSubtitle(rootSpace), - if (rootSpace.isLocked) - const Padding( - padding: EdgeInsets.only(left: 4.0), - child: Icon( - Icons.lock_outlined, + ), + SliverList.builder( + itemCount: joinedParents.length, + itemBuilder: (context, i) { + final displayname = + joinedParents[i].getLocalizedDisplayname(); + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 1, + ), + child: Material( + borderRadius: + BorderRadius.circular(AppConfig.borderRadius), + clipBehavior: Clip.hardEdge, + child: ListTile( + minVerticalPadding: 0, + leading: Icon( + Icons.adaptive.arrow_back_outlined, size: 16, ), - ), - ], - ), - onTap: () => chatListHandleSpaceTap( - context, - widget.controller, - rootSpaces[i], - ), - // subtitle: Text( - // L10n.of(context)!.numChats( - // rootSpace.spaceChildren.length.toString(), - // ), - // ), - // onTap: () => - // widget.controller.setActiveSpace(rootSpace.id), - // Pangea# - onLongPress: () => - _onSpaceChildContextMenu(null, rootSpace), - trailing: const Icon(Icons.chevron_right_outlined), - ), - ); - }, - childCount: rootSpaces.length, - ), - ), - ], - ), - ); - } - - final parentSpace = allSpaces.firstWhereOrNull( - (space) => - space.spaceChildren.any((child) => child.roomId == activeSpaceId), - ); - return PopScope( - canPop: parentSpace == null, - onPopInvoked: (pop) async { - if (pop) return; - if (parentSpace != null) { - widget.controller.setActiveSpace(parentSpace.id); - } - }, - child: SafeArea( - child: CustomScrollView( - controller: widget.scrollController, - slivers: [ - // #Pangea - // ChatListHeader(controller: widget.controller, globalSearch: false), - ChatListHeaderWrapper( - controller: widget.controller, - globalSearch: false, - ), - // Pangea# - SliverAppBar( - automaticallyImplyLeading: false, - primary: false, - titleSpacing: 0, - title: ListTile( - leading: BackButton( - // #Pangea - onPressed: () { - !FluffyThemes.isColumnMode(context) || - parentSpace?.id != null - ? widget.controller.setActiveSpace(parentSpace?.id) - : widget.controller.onDestinationSelected(0); - }, - // onPressed: () => - // widget.controller.setActiveSpace(parentSpace?.id), - // Pangea# - ), - title: Text( - parentSpace == null - // #Pangea - // ? L10n.of(context)!.allSpaces - ? !FluffyThemes.isColumnMode(context) - ? L10n.of(context)!.allSpaces - : L10n.of(context)!.allChats - // Pangea# - : parentSpace.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)!), - ), - ), - // #Pangea - // trailing: IconButton( - // icon: loading - // ? const CircularProgressIndicator.adaptive(strokeWidth: 2) - // : const Icon(Icons.refresh_outlined), - // onPressed: loading ? null : _refresh, - // ), - trailing: Tooltip( - message: L10n.of(context)!.refresh, - child: IconButton( - icon: loading - ? const CircularProgressIndicator.adaptive( - strokeWidth: 2, - ) - : const Icon(Icons.refresh_outlined), - onPressed: loading ? null : _refresh, - ), - ), - // Pangea# - ), - ), - Builder( - builder: (context) { - final response = _lastResponse[activeSpaceId]; - final error = this.error; - if (error != null) { - return SliverFillRemaining( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: Text(error.toLocalizedString(context)), - ), - IconButton( - onPressed: _refresh, - icon: const Icon(Icons.refresh_outlined), - ), - ], - ), - ); - } - if (response == null) { - return SliverFillRemaining( - child: Center( - child: Text(L10n.of(context)!.loadingPleaseWait), - ), - ); - } - // #Pangea - // final spaceChildren = response.rooms; - List spaceChildren = response.rooms; - final space = - Matrix.of(context).client.getRoomById(activeSpaceId); - if (space != null) { - spaceChildren = filterHierarchyResponse(space, spaceChildren); - } - spaceChildren.sort(sortSpaceChildren); - // Pangea# - final canLoadMore = response.nextBatch != null; - return SliverList( - delegate: SliverChildBuilderDelegate( - (context, i) { - if (canLoadMore && i == spaceChildren.length) { - return Padding( - padding: const EdgeInsets.all(16.0), - child: OutlinedButton.icon( - label: loading - ? const LinearProgressIndicator() - : Text(L10n.of(context)!.loadMore), - icon: const Icon(Icons.chevron_right_outlined), - onPressed: loading - ? null - : () { - // #Pangea - // loadHierarchy(response.nextBatch); - loadHierarchy(); - // Pangea# - }, - ), - ); - } - final spaceChild = spaceChildren[i]; - final room = client.getRoomById(spaceChild.roomId); - if (room != null && - !room.isSpace - // #Pangea - && - room.membership != Membership.leave - // Pangea# - ) { - // #Pangea - // return ChatListItem( - return ChatListItemWrapper( - controller: widget.controller, - // Pangea# - room, - onLongPress: () => - _onSpaceChildContextMenu(spaceChild, room), - activeChat: widget.controller.activeChat == room.id, - onTap: () => onChatTap(room, context), - ); - } - final isSpace = spaceChild.roomType == 'm.space'; - final topic = spaceChild.topic?.isEmpty ?? true - ? null - : spaceChild.topic; - if (spaceChild.roomId == activeSpaceId) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SearchTitle( - title: spaceChild.name ?? - spaceChild.canonicalAlias ?? - 'Space', - icon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10.0, - ), - child: Avatar( - size: 24, - mxContent: spaceChild.avatarUrl, - name: spaceChild.name, - ), - ), - color: Theme.of(context) - .colorScheme - .secondaryContainer - .withAlpha(128), - trailing: const Padding( - padding: EdgeInsets.symmetric(horizontal: 16.0), - // #Pangea - // child: Icon(Icons.edit_outlined), - child: Icon(Icons.settings_outlined), - // Pangea# - ), - // #Pangea - // onTap: () => _onJoinSpaceChild(spaceChild), - onTap: () => context.go( - '/rooms/${spaceChild.roomId}/details', - ), - // Pangea# - ), - if (activeSpace?.canChangeStateEvent( - EventTypes.SpaceChild, - ) == - true) - Material( - child: ListTile( - leading: const CircleAvatar( - child: Icon(Icons.group_add_outlined), + title: Row( + children: [ + Avatar( + mxContent: joinedParents[i].avatar, + name: displayname, + size: Avatar.defaultSize / 2, + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 4, + ), ), - title: - Text(L10n.of(context)!.addChatOrSubSpace), - trailing: - const Icon(Icons.chevron_right_outlined), - onTap: _addChatOrSubSpace, - ), + const SizedBox(width: 8), + Expanded(child: Text(displayname)), + ], ), - ], - ); - } - final name = spaceChild.name ?? - spaceChild.canonicalAlias ?? - L10n.of(context)!.chat; - if (widget.controller.isSearchMode && - !name.toLowerCase().contains( - widget.controller.searchController.text - .toLowerCase(), - )) { - return const SizedBox.shrink(); - } - return Material( - child: ListTile( - leading: Avatar( - mxContent: spaceChild.avatarUrl, - name: spaceChild.name, - //#Pangea - littleIcon: room?.roomTypeIcon, - //Pangea# + onTap: () => + widget.toParentSpace(joinedParents[i].id), + ), ), - title: Row( + ); + }, + ), + SliverList.builder( + itemCount: joinedRooms.length + 1, + itemBuilder: (context, i) { + if (i == 0) { + return Column( + mainAxisSize: MainAxisSize.min, children: [ - // #Pangea - // Expanded( - // child: - // Pangea# - Text( - name, - maxLines: 1, - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - // #Pangea - // ), - // Pangea# - if (!isSpace) ...[ - const Icon( - Icons.people_outline, - size: 16, - ), - const SizedBox(width: 4), - Text( - spaceChild.numJoinedMembers.toString(), - style: const TextStyle(fontSize: 14), + if (room.canChangeStateEvent( + EventTypes.SpaceChild, + ) && + filter.isEmpty) ...[ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 1, + ), + child: Material( + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), + clipBehavior: Clip.hardEdge, + child: ListTile( + onTap: _addChatOrSubspace, + leading: const CircleAvatar( + radius: Avatar.defaultSize / 2, + child: Icon(Icons.add_outlined), + ), + title: Text( + L10n.of(context)!.addChatOrSubSpace, + style: const TextStyle(fontSize: 14), + ), + ), + ), ), ], + SearchTitle( + title: L10n.of(context)!.joinedChats, + icon: const Icon(Icons.chat_outlined), + ), ], + ); + } + i--; + final joinedRoom = joinedRooms[i]; + return ChatListItem( + joinedRoom, + filter: filter, + onTap: () => widget.onChatTab(joinedRoom), + onLongPress: (context) => widget.onChatContext( + joinedRoom, + context, ), - // #Pangea - // onTap: () => room?.isSpace == true - // ? widget.controller.setActiveSpace(room!.id) - // : _onSpaceChildContextMenu(spaceChild, room), - onTap: room?.isSpace ?? false - ? () => chatListHandleSpaceTap( - context, - widget.controller, - room!, - ) - : () => _onJoinSpaceChild(spaceChild), - // Pangea# - onLongPress: () => - _onSpaceChildContextMenu(spaceChild, room), - subtitle: Text( - topic ?? - (isSpace - ? L10n.of(context)!.enterSpace - : L10n.of(context)!.enterRoom), - maxLines: 1, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, + activeChat: widget.activeChat == joinedRoom.id, + ); + }, + ), + SliverList.builder( + itemCount: (_discoveredChildren?.length ?? 0) + 2, + itemBuilder: (context, i) { + if (i == 0) { + return SearchTitle( + title: L10n.of(context)!.discover, + icon: const Icon(Icons.explore_outlined), + ); + } + i--; + if (i == (_discoveredChildren?.length ?? 0)) { + if (_noMoreRooms) { + return Padding( + padding: const EdgeInsets.all(12.0), + child: Center( + child: Text( + L10n.of(context)!.noMoreChatsFound, + style: const TextStyle(fontSize: 13), + ), + ), + ); + } + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 2.0, + ), + child: TextButton( + onPressed: _isLoading ? null : loadHierarchy, + child: _isLoading + ? LinearProgressIndicator( + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), + ) + : Text(L10n.of(context)!.loadMore), + ), + ); + } + final item = _discoveredChildren![i]; + final displayname = item.name ?? + item.canonicalAlias ?? + L10n.of(context)!.emptyChat; + if (!displayname.toLowerCase().contains(filter)) { + return const SizedBox.shrink(); + } + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 1, + ), + child: Material( + borderRadius: + BorderRadius.circular(AppConfig.borderRadius), + clipBehavior: Clip.hardEdge, + child: ListTile( + onTap: () => _joinChildRoom(item), + leading: Avatar( + mxContent: item.avatarUrl, + name: displayname, + borderRadius: item.roomType == 'm.space' + ? BorderRadius.circular( + AppConfig.borderRadius / 2, + ) + : null, + ), + title: Row( + children: [ + Expanded( + child: Text( + displayname, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(width: 8), + const Icon( + Icons.add_circle_outline_outlined, + ), + ], + ), + subtitle: Text( + item.topic ?? + L10n.of(context)!.countParticipants( + item.numJoinedMembers, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), ), ), - trailing: isSpace - ? const Icon(Icons.chevron_right_outlined) - : null, - ), - ); - }, - childCount: spaceChildren.length + (canLoadMore ? 1 : 0), - ), + ); + }, + ), + ], ); }, ), - ], - ), - ), ); } } -enum SpaceChildContextAction { - join, +enum SpaceActions { + settings, + invite, leave, - removeFromSpace, - // #Pangea - // deleteChat, - archive, - addToSpace - // Pangea# } - -enum AddRoomType { chat, subspace } diff --git a/lib/pages/chat_list/start_chat_fab.dart b/lib/pages/chat_list/start_chat_fab.dart deleted file mode 100644 index f25374f4e..000000000 --- a/lib/pages/chat_list/start_chat_fab.dart +++ /dev/null @@ -1,125 +0,0 @@ -import 'dart:core'; - -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; - -import '../../config/themes.dart'; -import 'chat_list.dart'; - -class StartChatFloatingActionButton extends StatelessWidget { - final ActiveFilter activeFilter; - final ValueNotifier scrolledToTop; - final bool roomsIsEmpty; - // #Pangea - final ChatListController controller; - // Pangea# - final void Function() createNewSpace; - - const StartChatFloatingActionButton({ - super.key, - required this.activeFilter, - required this.scrolledToTop, - required this.roomsIsEmpty, - required this.createNewSpace, - // #Pangea - required this.controller, - // Pangea# - }); - - void _onPressed(BuildContext context) async { - //#Pangea - if (controller.activeSpaceId != null) { - context.go( - '/rooms/newgroup${controller.activeSpaceId != null ? '?spaceId=${controller.activeSpaceId}' : ''}', - ); - return; - } - //Pangea# - switch (activeFilter) { - case ActiveFilter.allChats: - case ActiveFilter.messages: - // #Pangea - // context.go('/rooms/newprivatechat'); - // break; - // Pangea# - case ActiveFilter.groups: - // #Pangea - // context.go('/rooms/newgroup'); - context.go( - '/rooms/newgroup${controller.activeSpaceId != null ? '?spaceId=${controller.activeSpaceId}' : ''}', - ); - // Pangea# - break; - case ActiveFilter.spaces: - // #Pangea - // createNewSpace(); - context.go('/rooms/newspace'); - // Pangea# - break; - } - } - - IconData get icon { - // #Pangea - if (controller.activeSpaceId != null) { - return Icons.group_add_outlined; - } - // Pangea# - switch (activeFilter) { - case ActiveFilter.allChats: - case ActiveFilter.messages: - // #Pangea - // return Icons.add_outlined; - // Pangea# - case ActiveFilter.groups: - return Icons.group_add_outlined; - case ActiveFilter.spaces: - return Icons.workspaces_outlined; - } - } - - String getLabel(BuildContext context) { - // #Pangea - if (controller.activeSpaceId != null) { - return L10n.of(context)!.newGroup; - } - // Pangea# - switch (activeFilter) { - case ActiveFilter.allChats: - case ActiveFilter.messages: - return roomsIsEmpty - ? L10n.of(context)!.startFirstChat - : L10n.of(context)!.newChat; - case ActiveFilter.groups: - return L10n.of(context)!.newGroup; - case ActiveFilter.spaces: - return L10n.of(context)!.newSpace; - } - } - - @override - Widget build(BuildContext context) { - return ValueListenableBuilder( - valueListenable: scrolledToTop, - builder: (context, scrolledToTop, _) => AnimatedSize( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - clipBehavior: Clip.none, - child: scrolledToTop - ? FloatingActionButton.extended( - onPressed: () => _onPressed(context), - icon: Icon(icon), - label: Text( - getLabel(context), - overflow: TextOverflow.fade, - ), - ) - : FloatingActionButton( - onPressed: () => _onPressed(context), - child: Icon(icon), - ), - ), - ); - } -} diff --git a/lib/pages/chat_list/status_msg_list.dart b/lib/pages/chat_list/status_msg_list.dart index 9b69e2a16..2d31537cc 100644 --- a/lib/pages/chat_list/status_msg_list.dart +++ b/lib/pages/chat_list/status_msg_list.dart @@ -116,17 +116,17 @@ class PresenceAvatar extends StatelessWidget { return FutureBuilder( future: client.getProfileFromUserId(presence.userid), builder: (context, snapshot) { + final theme = Theme.of(context); + final profile = snapshot.data; final displayName = profile?.displayName ?? presence.userid.localpart ?? presence.userid; final statusMsg = presence.statusMsg; - final statusMsgBubbleElevation = - Theme.of(context).appBarTheme.scrolledUnderElevation ?? 4; - final statusMsgBubbleShadowColor = - Theme.of(context).colorScheme.onSurface; - final statusMsgBubbleColor = Colors.white.withAlpha(245); + const statusMsgBubbleElevation = 6.0; + final statusMsgBubbleShadowColor = theme.colorScheme.surface; + final statusMsgBubbleColor = Colors.white.withOpacity(0.9); return Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: SizedBox( diff --git a/lib/pages/chat_list/utils/on_chat_tap.dart b/lib/pages/chat_list/utils/on_chat_tap.dart deleted file mode 100644 index f7daa248e..000000000 --- a/lib/pages/chat_list/utils/on_chat_tap.dart +++ /dev/null @@ -1,136 +0,0 @@ -import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:fluffychat/pages/chat/send_file_dialog.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:future_loading_dialog/future_loading_dialog.dart'; -import 'package:go_router/go_router.dart'; -import 'package:matrix/matrix.dart'; - -void onChatTap(Room room, BuildContext context) async { - if (room.membership == Membership.invite) { - final inviterId = - room.getState(EventTypes.RoomMember, room.client.userID!)?.senderId; - final inviteAction = await showModalActionSheet( - context: context, - message: room.isDirectChat - ? L10n.of(context)!.invitePrivateChat - : L10n.of(context)!.inviteGroupChat, - title: room.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), - actions: [ - SheetAction( - key: InviteActions.accept, - label: L10n.of(context)!.accept, - icon: Icons.check_outlined, - isDefaultAction: true, - ), - SheetAction( - key: InviteActions.decline, - label: L10n.of(context)!.decline, - icon: Icons.close_outlined, - isDestructiveAction: true, - ), - SheetAction( - key: InviteActions.block, - label: L10n.of(context)!.block, - icon: Icons.block_outlined, - isDestructiveAction: true, - ), - ], - ); - if (inviteAction == null) return; - if (inviteAction == InviteActions.block) { - context.go('/rooms/settings/security/ignorelist', extra: inviterId); - return; - } - if (inviteAction == InviteActions.decline) { - // #Pangea - if (!room.isSpace && - room.membership == Membership.join && - room.isUnread) { - await room.markUnread(false); - } - // Pangea# - await showFutureLoadingDialog( - context: context, - future: room.leave, - ); - return; - } - final joinResult = await showFutureLoadingDialog( - context: context, - future: () async { - final waitForRoom = room.client.waitForRoomInSync( - room.id, - join: true, - ); - if (await room.leaveIfFull()) { - throw L10n.of(context)!.roomFull; - } - await room.join(); - await waitForRoom; - }, - ); - if (joinResult.error != null) return; - } - - if (room.membership == Membership.ban) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(L10n.of(context)!.youHaveBeenBannedFromThisChat), - ), - ); - return; - } - - if (room.membership == Membership.leave) { - context.go('/rooms/archive/${room.id}'); - return; - } - - // Share content into this room - final shareContent = Matrix.of(context).shareContent; - if (shareContent != null) { - final shareFile = shareContent.tryGet('file'); - if (shareContent.tryGet('msgtype') == 'chat.fluffy.shared_file' && - shareFile != null) { - await showDialog( - context: context, - useRootNavigator: false, - builder: (c) => SendFileDialog( - files: [shareFile], - room: room, - ), - ); - Matrix.of(context).shareContent = null; - } else { - final consent = await showOkCancelAlertDialog( - context: context, - title: L10n.of(context)!.forward, - message: L10n.of(context)!.forwardMessageTo( - room.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), - ), - okLabel: L10n.of(context)!.forward, - cancelLabel: L10n.of(context)!.cancel, - ); - if (consent == OkCancelResult.cancel) { - Matrix.of(context).shareContent = null; - return; - } - if (consent == OkCancelResult.ok) { - room.sendEvent(shareContent); - Matrix.of(context).shareContent = null; - } - } - } - - context.go('/rooms/${room.id}'); -} - -enum InviteActions { - accept, - decline, - block, -} diff --git a/lib/pages/chat_members/chat_members_view.dart b/lib/pages/chat_members/chat_members_view.dart index b699fcef0..daa681a52 100644 --- a/lib/pages/chat_members/chat_members_view.dart +++ b/lib/pages/chat_members/chat_members_view.dart @@ -34,6 +34,7 @@ class ChatMembersView extends StatelessWidget { (room.summary.mInvitedMemberCount ?? 0); final error = controller.error; + final theme = Theme.of(context); return Scaffold( appBar: AppBar( @@ -90,6 +91,16 @@ class ChatMembersView extends StatelessWidget { controller: controller.filterController, onChanged: controller.setFilter, decoration: InputDecoration( + filled: true, + fillColor: theme.colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(99), + ), + hintStyle: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontWeight: FontWeight.normal, + ), prefixIcon: const Icon(Icons.search_outlined), hintText: L10n.of(context)!.search, ), diff --git a/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart b/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart index 2b1dff187..8d03b043b 100644 --- a/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart +++ b/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart @@ -13,6 +13,8 @@ class ChatPermissionsSettingsView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return Scaffold( appBar: AppBar( leading: const Center(child: BackButton()), @@ -57,6 +59,22 @@ class ChatPermissionsSettingsView extends StatelessWidget { // Pangea# return Column( children: [ + ListTile( + leading: const Icon(Icons.info_outlined), + subtitle: Text( + L10n.of(context)!.chatPermissionsDescription, + ), + ), + Divider(color: theme.dividerColor), + ListTile( + title: Text( + L10n.of(context)!.chatPermissions, + style: TextStyle( + color: theme.colorScheme.primary, + fontWeight: FontWeight.bold, + ), + ), + ), Column( mainAxisSize: MainAxisSize.min, children: [ @@ -73,13 +91,12 @@ class ChatPermissionsSettingsView extends StatelessWidget { canEdit: room.canChangePowerLevel, ), // #Pangea - // Why would teacher need to stop students from seeing notifications? - // Divider(color: Theme.of(context).dividerColor), + // Divider(color: theme.dividerColor), // ListTile( // title: Text( // L10n.of(context)!.notifications, // style: TextStyle( - // color: Theme.of(context).colorScheme.primary, + // color: theme.colorScheme.primary, // fontWeight: FontWeight.bold, // ), // ), @@ -109,22 +126,17 @@ class ChatPermissionsSettingsView extends StatelessWidget { // ); // }, // ), - // Only show if there are actually items in this category - if (eventsPowerLevels.isNotEmpty) - // Pangea# - Divider(color: Theme.of(context).dividerColor), - // #Pangea - if (eventsPowerLevels.isNotEmpty) - // Pangea# - ListTile( - title: Text( - L10n.of(context)!.configureChat, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontWeight: FontWeight.bold, - ), + // Pangea# + Divider(color: theme.dividerColor), + ListTile( + title: Text( + L10n.of(context)!.configureChat, + style: TextStyle( + color: theme.colorScheme.primary, + fontWeight: FontWeight.bold, ), ), + ), for (final entry in eventsPowerLevels.entries) PermissionsListTile( permissionKey: entry.key, diff --git a/lib/pages/chat_permissions_settings/permission_list_tile.dart b/lib/pages/chat_permissions_settings/permission_list_tile.dart index 04a2d3a60..2914f9112 100644 --- a/lib/pages/chat_permissions_settings/permission_list_tile.dart +++ b/lib/pages/chat_permissions_settings/permission_list_tile.dart @@ -1,6 +1,4 @@ import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; -import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; @@ -29,7 +27,7 @@ class PermissionsListTile extends StatelessWidget { case 'events_default': return L10n.of(context)!.sendMessages; case 'state_default': - return L10n.of(context)!.configureChat; + return L10n.of(context)!.changeGeneralChatSettings; case 'ban': return L10n.of(context)!.banFromChat; case 'kick': @@ -37,23 +35,25 @@ class PermissionsListTile extends StatelessWidget { case 'redact': return L10n.of(context)!.deleteMessage; case 'invite': - return L10n.of(context)!.inviteContact; + return L10n.of(context)!.inviteOtherUsers; } } else if (category == 'notifications') { switch (permissionKey) { case 'rooms': - return L10n.of(context)!.notifications; + return L10n.of(context)!.sendRoomNotifications; } } else if (category == 'events') { switch (permissionKey) { case EventTypes.RoomName: return L10n.of(context)!.changeTheNameOfTheGroup; + case EventTypes.RoomTopic: + return L10n.of(context)!.changeTheDescriptionOfTheGroup; case EventTypes.RoomPowerLevels: - return L10n.of(context)!.chatPermissions; + return L10n.of(context)!.changeTheChatPermissions; case EventTypes.HistoryVisibility: - return L10n.of(context)!.visibilityOfTheChatHistory; + return L10n.of(context)!.changeTheVisibilityOfChatHistory; case EventTypes.RoomCanonicalAlias: - return L10n.of(context)!.setInvitationLink; + return L10n.of(context)!.changeTheCanonicalRoomAlias; case EventTypes.RoomAvatar: return L10n.of(context)!.editRoomAvatar; case EventTypes.RoomTombstone: @@ -69,41 +69,48 @@ class PermissionsListTile extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + + final color = permission >= 100 + ? Colors.orangeAccent + : permission >= 50 + ? Colors.blueAccent + : Colors.greenAccent; return ListTile( - title: Text(getLocalizedPowerLevelString(context)), - subtitle: Text( - // #Pangea - // L10n.of(context)!.minimumPowerLevel(permission.toString()), - L10n.of(context)!.minimumPowerLevel( - Matrix.of(context).client.powerLevelName( - permission, - L10n.of(context)!, - ) ?? - permission.toString(), - ), - // Pangea# + title: Text( + getLocalizedPowerLevelString(context), + style: theme.textTheme.titleSmall, ), trailing: Material( + color: color.withAlpha(32), borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), - color: Theme.of(context).colorScheme.onInverseSurface, child: DropdownButton( padding: const EdgeInsets.symmetric(horizontal: 8.0), borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), underline: const SizedBox.shrink(), onChanged: canEdit ? onChanged : null, - value: {0, 50, 100}.contains(permission) ? permission : null, + value: permission, items: [ DropdownMenuItem( - value: 0, - child: Text(L10n.of(context)!.user), + value: permission < 50 ? permission : 0, + child: Text( + L10n.of(context)!.userLevel(permission < 50 ? permission : 0), + ), ), DropdownMenuItem( - value: 50, - child: Text(L10n.of(context)!.moderator), + value: permission < 100 && permission >= 50 ? permission : 50, + child: Text( + L10n.of(context)!.moderatorLevel( + permission < 100 && permission >= 50 ? permission : 50, + ), + ), ), DropdownMenuItem( - value: 100, - child: Text(L10n.of(context)!.admin), + value: permission >= 100 ? permission : 100, + child: Text( + L10n.of(context)! + .adminLevel(permission >= 100 ? permission : 100), + ), ), DropdownMenuItem( value: null, diff --git a/lib/pages/chat_search/chat_search_files_tab.dart b/lib/pages/chat_search/chat_search_files_tab.dart index 85525ab6f..e981efb19 100644 --- a/lib/pages/chat_search/chat_search_files_tab.dart +++ b/lib/pages/chat_search/chat_search_files_tab.dart @@ -28,6 +28,7 @@ class ChatSearchFilesTab extends StatelessWidget { return StreamBuilder( stream: searchStream, builder: (context, snapshot) { + final theme = Theme.of(context); final events = snapshot.data?.$1; if (searchStream == null || events == null) { return Column( @@ -82,10 +83,8 @@ class ChatSearchFilesTab extends StatelessWidget { padding: const EdgeInsets.all(16.0), child: TextButton.icon( style: TextButton.styleFrom( - backgroundColor: - Theme.of(context).colorScheme.secondaryContainer, - foregroundColor: - Theme.of(context).colorScheme.onSecondaryContainer, + backgroundColor: theme.colorScheme.secondaryContainer, + foregroundColor: theme.colorScheme.onSecondaryContainer, ), onPressed: () => startSearch( prevBatch: nextBatch, @@ -127,21 +126,21 @@ class ChatSearchFilesTab extends StatelessWidget { Expanded( child: Container( height: 1, - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), ), Padding( padding: const EdgeInsets.all(8.0), child: Text( event.originServerTs.localizedTime(context), - style: Theme.of(context).textTheme.labelSmall, + style: theme.textTheme.labelSmall, textAlign: TextAlign.center, ), ), Expanded( child: Container( height: 1, - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), ), ], @@ -151,7 +150,7 @@ class ChatSearchFilesTab extends StatelessWidget { Material( borderRadius: BorderRadius.circular(AppConfig.borderRadius), - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, clipBehavior: Clip.hardEdge, child: ListTile( leading: const Icon(Icons.file_present_outlined), diff --git a/lib/pages/chat_search/chat_search_images_tab.dart b/lib/pages/chat_search/chat_search_images_tab.dart index 9f8c1f0c9..90cdc839b 100644 --- a/lib/pages/chat_search/chat_search_images_tab.dart +++ b/lib/pages/chat_search/chat_search_images_tab.dart @@ -28,6 +28,7 @@ class ChatSearchImagesTab extends StatelessWidget { return StreamBuilder( stream: searchStream, builder: (context, snapshot) { + final theme = Theme.of(context); final events = snapshot.data?.$1; if (searchStream == null || events == null) { return Column( @@ -91,10 +92,8 @@ class ChatSearchImagesTab extends StatelessWidget { padding: const EdgeInsets.all(16.0), child: TextButton.icon( style: TextButton.styleFrom( - backgroundColor: - Theme.of(context).colorScheme.secondaryContainer, - foregroundColor: - Theme.of(context).colorScheme.onSecondaryContainer, + backgroundColor: theme.colorScheme.secondaryContainer, + foregroundColor: theme.colorScheme.onSecondaryContainer, ), onPressed: () => startSearch( prevBatch: nextBatch, @@ -119,7 +118,7 @@ class ChatSearchImagesTab extends StatelessWidget { Expanded( child: Container( height: 1, - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), ), Padding( @@ -128,14 +127,14 @@ class ChatSearchImagesTab extends StatelessWidget { DateFormat.yMMMM( Localizations.localeOf(context).languageCode, ).format(eventsByMonthList[i].key), - style: Theme.of(context).textTheme.labelSmall, + style: theme.textTheme.labelSmall, textAlign: TextAlign.center, ), ), Expanded( child: Container( height: 1, - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), ), ], diff --git a/lib/pages/chat_search/chat_search_message_tab.dart b/lib/pages/chat_search/chat_search_message_tab.dart index 7542d6ae9..a2d34fa9e 100644 --- a/lib/pages/chat_search/chat_search_message_tab.dart +++ b/lib/pages/chat_search/chat_search_message_tab.dart @@ -33,6 +33,7 @@ class ChatSearchMessageTab extends StatelessWidget { key: ValueKey(searchQuery), stream: searchStream, builder: (context, snapshot) { + final theme = Theme.of(context); if (searchStream == null) { return Column( mainAxisAlignment: MainAxisAlignment.center, @@ -55,7 +56,7 @@ class ChatSearchMessageTab extends StatelessWidget { child: ListView.separated( itemCount: events.length + 1, separatorBuilder: (context, _) => Divider( - color: Theme.of(context).dividerColor, + color: theme.dividerColor, height: 1, ), itemBuilder: (context, i) { @@ -79,10 +80,8 @@ class ChatSearchMessageTab extends StatelessWidget { padding: const EdgeInsets.all(16.0), child: TextButton.icon( style: TextButton.styleFrom( - backgroundColor: - Theme.of(context).colorScheme.secondaryContainer, - foregroundColor: - Theme.of(context).colorScheme.onSecondaryContainer, + backgroundColor: theme.colorScheme.secondaryContainer, + foregroundColor: theme.colorScheme.onSecondaryContainer, ), onPressed: () => startSearch( prevBatch: nextBatch, @@ -130,6 +129,8 @@ class _MessageSearchResultListTile extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return ListTile( title: Row( children: [ @@ -153,9 +154,9 @@ class _MessageSearchResultListTile extends StatelessWidget { subtitle: Linkify( options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, decoration: TextDecoration.underline, - decorationColor: Theme.of(context).colorScheme.primary, + decorationColor: theme.colorScheme.primary, ), onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), text: event diff --git a/lib/pages/chat_search/chat_search_view.dart b/lib/pages/chat_search/chat_search_view.dart index e08f25a2b..e29fa1d01 100644 --- a/lib/pages/chat_search/chat_search_view.dart +++ b/lib/pages/chat_search/chat_search_view.dart @@ -31,6 +31,8 @@ class ChatSearchView extends StatelessWidget { ); } + final theme = Theme.of(context); + return Scaffold( appBar: AppBar( leading: const Center(child: BackButton()), @@ -59,6 +61,16 @@ class ChatSearchView extends StatelessWidget { decoration: InputDecoration( hintText: L10n.of(context)!.search, suffixIcon: const Icon(Icons.search_outlined), + filled: true, + fillColor: theme.colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(99), + ), + hintStyle: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontWeight: FontWeight.normal, + ), ), ), ), diff --git a/lib/pages/device_settings/device_settings_view.dart b/lib/pages/device_settings/device_settings_view.dart index e107d30c9..20fb9e800 100644 --- a/lib/pages/device_settings/device_settings_view.dart +++ b/lib/pages/device_settings/device_settings_view.dart @@ -22,6 +22,7 @@ class DevicesSettingsView extends StatelessWidget { child: FutureBuilder( future: controller.loadUserDevices(context), builder: (BuildContext context, snapshot) { + final theme = Theme.of(context); if (snapshot.hasError) { return Center( child: Column( @@ -58,7 +59,7 @@ class DevicesSettingsView extends StatelessWidget { L10n.of(context)!.thisDevice, style: TextStyle( fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), textAlign: TextAlign.left, ), @@ -86,12 +87,10 @@ class DevicesSettingsView extends StatelessWidget { L10n.of(context)!.removeAllOtherDevices, ), style: TextButton.styleFrom( - foregroundColor: Theme.of(context) - .colorScheme - .onErrorContainer, - backgroundColor: Theme.of(context) - .colorScheme - .errorContainer, + foregroundColor: + theme.colorScheme.onErrorContainer, + backgroundColor: + theme.colorScheme.errorContainer, ), icon: controller.loadingDeletingDevices ? const CircularProgressIndicator.adaptive( diff --git a/lib/pages/homeserver_picker/homeserver_app_bar.dart b/lib/pages/homeserver_picker/homeserver_app_bar.dart deleted file mode 100644 index d041c8852..000000000 --- a/lib/pages/homeserver_picker/homeserver_app_bar.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/pages/homeserver_picker/public_homeserver.dart'; -import 'package:fluffychat/utils/localized_exception_extension.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:flutter_typeahead/flutter_typeahead.dart'; - -import 'homeserver_bottom_sheet.dart'; -import 'homeserver_picker.dart'; - -class HomeserverAppBar extends StatelessWidget { - final HomeserverPickerController controller; - - const HomeserverAppBar({super.key, required this.controller}); - - @override - Widget build(BuildContext context) { - return TypeAheadField( - decorationBuilder: (context, child) => ConstrainedBox( - constraints: const BoxConstraints(maxHeight: 256), - child: Material( - borderRadius: BorderRadius.circular(AppConfig.borderRadius), - elevation: Theme.of(context).appBarTheme.scrolledUnderElevation ?? 4, - shadowColor: - Theme.of(context).appBarTheme.shadowColor ?? Colors.black, - child: child, - ), - ), - emptyBuilder: (context) => ListTile( - leading: const Icon(Icons.search_outlined), - title: Text(L10n.of(context)!.nothingFound), - ), - loadingBuilder: (context) => ListTile( - leading: const CircularProgressIndicator.adaptive(strokeWidth: 2), - title: Text(L10n.of(context)!.loadingPleaseWait), - ), - errorBuilder: (context, error) => ListTile( - leading: const Icon(Icons.error_outlined), - title: Text( - error.toLocalizedString(context), - ), - ), - itemBuilder: (context, homeserver) => ListTile( - title: Text(homeserver.name), - subtitle: homeserver.description == null - ? null - : Text(homeserver.description ?? ''), - trailing: IconButton( - icon: const Icon(Icons.info_outlined), - onPressed: () => showModalBottomSheet( - context: context, - builder: (_) => HomeserverBottomSheet( - homeserver: homeserver, - ), - ), - ), - ), - suggestionsCallback: (pattern) async { - pattern = pattern.toLowerCase().trim(); - final homeservers = await controller.loadHomeserverList(); - final matches = homeservers - .where( - (homeserver) => - homeserver.name.toLowerCase().contains(pattern) || - (homeserver.description?.toLowerCase().contains(pattern) ?? - false), - ) - .toList(); - if (pattern.contains('.') && - pattern.split('.').any((part) => part.isNotEmpty) && - !matches.any((homeserver) => homeserver.name == pattern)) { - matches.add(PublicHomeserver(name: pattern)); - } - return matches; - }, - onSelected: (suggestion) { - controller.homeserverController.text = suggestion.name; - controller.checkHomeserverAction(); - }, - controller: controller.homeserverController, - builder: (context, textEditingController, focusNode) => TextField( - enabled: !controller.isLoggingIn, - controller: textEditingController, - focusNode: focusNode, - decoration: InputDecoration( - prefixIcon: Navigator.of(context).canPop() - ? IconButton( - onPressed: Navigator.of(context).pop, - icon: const Icon(Icons.arrow_back), - ) - : null, - fillColor: FluffyThemes.isColumnMode(context) - ? Theme.of(context).colorScheme.surface - // ignore: deprecated_member_use - : Theme.of(context).colorScheme.surfaceVariant, - prefixText: '${L10n.of(context)!.homeserver}: ', - hintText: L10n.of(context)!.enterYourHomeserver, - suffixIcon: const Icon(Icons.search), - ), - textInputAction: TextInputAction.search, - onSubmitted: controller.checkHomeserverAction, - autocorrect: false, - ), - ); - } -} diff --git a/lib/pages/homeserver_picker/homeserver_bottom_sheet.dart b/lib/pages/homeserver_picker/homeserver_bottom_sheet.dart deleted file mode 100644 index 18256d6fb..000000000 --- a/lib/pages/homeserver_picker/homeserver_bottom_sheet.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:url_launcher/url_launcher_string.dart'; - -import 'package:fluffychat/pages/homeserver_picker/public_homeserver.dart'; - -class HomeserverBottomSheet extends StatelessWidget { - final PublicHomeserver homeserver; - const HomeserverBottomSheet({required this.homeserver, super.key}); - - @override - Widget build(BuildContext context) { - final description = homeserver.description; - final registration = homeserver.regLink; - final jurisdiction = homeserver.staffJur; - final homeserverSoftware = homeserver.software; - return Scaffold( - appBar: AppBar( - title: Text(homeserver.name), - ), - body: ListView( - children: [ - if (description != null && description.isNotEmpty) - ListTile( - leading: const Icon(Icons.info_outlined), - title: Text(description), - ), - if (jurisdiction != null && jurisdiction.isNotEmpty) - ListTile( - leading: const Icon(Icons.location_city_outlined), - title: Text(jurisdiction), - ), - if (homeserverSoftware != null && homeserverSoftware.isNotEmpty) - ListTile( - leading: const Icon(Icons.domain_outlined), - title: Text(homeserverSoftware), - ), - ListTile( - onTap: () => launchUrlString(homeserver.name), - leading: const Icon(Icons.link_outlined), - title: Text(homeserver.name), - ), - if (registration != null) - ListTile( - onTap: () => launchUrlString(registration), - leading: const Icon(Icons.person_add_outlined), - title: Text(registration), - ), - ], - ), - ); - } -} diff --git a/lib/pages/homeserver_picker/homeserver_picker.dart b/lib/pages/homeserver_picker/homeserver_picker.dart index df6dec2b4..41377d9af 100644 --- a/lib/pages/homeserver_picker/homeserver_picker.dart +++ b/lib/pages/homeserver_picker/homeserver_picker.dart @@ -1,12 +1,10 @@ import 'dart:async'; -import 'dart:convert'; import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:collection/collection.dart'; import 'package:file_picker/file_picker.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/homeserver_picker/homeserver_picker_view.dart'; -import 'package:fluffychat/pages/homeserver_picker/public_homeserver.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/firebase_analytics.dart'; import 'package:fluffychat/utils/platform_infos.dart'; @@ -27,7 +25,8 @@ import 'package:universal_html/html.dart' as html; import '../../utils/localized_exception_extension.dart'; class HomeserverPicker extends StatefulWidget { - const HomeserverPicker({super.key}); + final bool addMultiAccount; + const HomeserverPicker({required this.addMultiAccount, super.key}); @override HomeserverPickerController createState() => HomeserverPickerController(); @@ -37,9 +36,11 @@ class HomeserverPickerController extends State { bool isLoading = false; bool isLoggingIn = false; - final TextEditingController homeserverController = TextEditingController( - text: AppConfig.defaultHomeserver, - ); + // #Pangea + // final TextEditingController homeserverController = TextEditingController( + // text: AppConfig.defaultHomeserver, + // ); + // Pangea# String? error; @@ -65,36 +66,82 @@ class HomeserverPickerController extends State { String? _lastCheckedUrl; + Timer? _checkHomeserverCooldown; + + tryCheckHomeserverActionWithCooldown([_]) { + _checkHomeserverCooldown?.cancel(); + _checkHomeserverCooldown = Timer( + const Duration(milliseconds: 500), + checkHomeserverAction, + ); + } + + tryCheckHomeserverActionWithoutCooldown([_]) { + _checkHomeserverCooldown?.cancel(); + _lastCheckedUrl = null; + checkHomeserverAction(); + } + + // #Pangea + Map? _rawLoginTypes; + // Pangea# + /// Starts an analysis of the given homeserver. It uses the current domain and /// makes sure that it is prefixed with https. Then it searches for the /// well-known information and forwards to the login page depending on the /// login type. Future checkHomeserverAction([_]) async { - homeserverController.text = - homeserverController.text.trim().toLowerCase().replaceAll(' ', '-'); - if (homeserverController.text == _lastCheckedUrl) return; - _lastCheckedUrl = homeserverController.text; + // #Pangea + // homeserverController.text = + // homeserverController.text.trim().toLowerCase().replaceAll(' ', '-'); + + // if (homeserverController.text.isEmpty) { + // setState(() { + // error = loginFlows = null; + // isLoading = false; + // Matrix.of(context).getLoginClient().homeserver = null; + // }); + // return; + // } + // if (_lastCheckedUrl == homeserverController.text) return; + + // _lastCheckedUrl = homeserverController.text; + _lastCheckedUrl = AppConfig.defaultHomeserver; + // Pangea# setState(() { - error = _rawLoginTypes = loginFlows = null; + error = loginFlows = null; isLoading = true; }); try { - var homeserver = Uri.parse(homeserverController.text); + // #Pangea + // var homeserver = Uri.parse(homeserverController.text); + // if (homeserver.scheme.isEmpty) { + // homeserver = Uri.https(homeserverController.text, ''); + // } + var homeserver = Uri.parse(AppConfig.defaultHomeserver); if (homeserver.scheme.isEmpty) { - homeserver = Uri.https(homeserverController.text, ''); + homeserver = Uri.https(AppConfig.defaultHomeserver, ''); } + // Pangea# final client = Matrix.of(context).getLoginClient(); final (_, _, loginFlows) = await client.checkHomeserver(homeserver); this.loginFlows = loginFlows; + // #Pangea if (supportsSso) { _rawLoginTypes = await client.request( RequestType.GET, '/client/v3/login', ); } + // Pangea# } catch (e) { - setState(() => error = (e).toLocalizedString(context)); + setState( + () => error = (e).toLocalizedString( + context, + ExceptionContext.checkHomeserver, + ), + ); } finally { if (mounted) { setState(() => isLoading = false); @@ -114,12 +161,11 @@ class HomeserverPickerController extends State { bool get supportsPasswordLogin => _supportsFlow('m.login.password'); - Map? _rawLoginTypes; - - // #Pangea - // void ssoLoginAction(String id) async { - void ssoLoginAction(IdentityProvider provider) async { - //Pangea# + void ssoLoginAction( + // #Pangea + IdentityProvider provider, + // Pangea# + ) async { final redirectUrl = kIsWeb ? Uri.parse(html.window.location.href) .resolveUri( @@ -132,7 +178,7 @@ class HomeserverPickerController extends State { final url = Matrix.of(context).getLoginClient().homeserver!.replace( // #Pangea - // path: '/_matrix/client/v3/login/sso/redirect${id == null ? '' : '/$id'}', + // path: '/_matrix/client/v3/login/sso/redirect', path: '/_matrix/client/v3/login/sso/redirect${provider.id == null ? '' : '/${provider.id}'}', // Pangea# @@ -142,6 +188,7 @@ class HomeserverPickerController extends State { final urlScheme = isDefaultPlatform ? Uri.parse(redirectUrl).scheme : "http://localhost:3001"; + // #Pangea // final result = await FlutterWebAuth2.authenticate( // url: url.toString(), @@ -200,39 +247,6 @@ class HomeserverPickerController extends State { } } - List? get identityProviders { - final loginTypes = _rawLoginTypes; - if (loginTypes == null) return null; - final List? rawProviders = - loginTypes.tryGetList('flows')?.singleWhereOrNull( - (flow) => flow['type'] == AuthenticationTypes.sso, - )['identity_providers'] ?? - [ - {'id': null}, - ]; - if (rawProviders == null) return null; - final list = - rawProviders.map((json) => IdentityProvider.fromJson(json)).toList(); - if (PlatformInfos.isCupertinoStyle) { - list.sort((a, b) => a.brand == 'apple' ? -1 : 1); - } - return list; - } - - List? cachedHomeservers; - - Future> loadHomeserverList() async { - if (cachedHomeservers != null) return cachedHomeservers!; - final result = await Matrix.of(context) - .getLoginClient() - .httpClient - .get(AppConfig.homeserverList); - final resultJson = jsonDecode(result.body)['public_servers'] as List; - final homeserverList = - resultJson.map((json) => PublicHomeserver.fromJson(json)).toList(); - return cachedHomeservers = homeserverList; - } - void login() => context.push( '${GoRouter.of(context).routeInformationProvider.value.uri.path}/login', ); @@ -276,6 +290,27 @@ class HomeserverPickerController extends State { } } } + + // #Pangea + List? get identityProviders { + final loginTypes = _rawLoginTypes; + if (loginTypes == null) return null; + final List? rawProviders = + loginTypes.tryGetList('flows')?.singleWhereOrNull( + (flow) => flow['type'] == AuthenticationTypes.sso, + )['identity_providers'] ?? + [ + {'id': null}, + ]; + if (rawProviders == null) return null; + final list = + rawProviders.map((json) => IdentityProvider.fromJson(json)).toList(); + if (PlatformInfos.isCupertinoStyle) { + list.sort((a, b) => a.brand == 'apple' ? -1 : 1); + } + return list; + } + // Pangea# } class IdentityProvider { diff --git a/lib/pages/homeserver_picker/homeserver_picker_view.dart b/lib/pages/homeserver_picker/homeserver_picker_view.dart index 9e8ca13ff..1b0c7f59f 100644 --- a/lib/pages/homeserver_picker/homeserver_picker_view.dart +++ b/lib/pages/homeserver_picker/homeserver_picker_view.dart @@ -1,5 +1,4 @@ import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/pangea/pages/connect/p_sso_button.dart'; import 'package:fluffychat/pangea/widgets/common/pangea_logo_svg.dart'; import 'package:fluffychat/pangea/widgets/signup/signup_buttons.dart'; @@ -16,25 +15,17 @@ class HomeserverPickerView extends StatelessWidget { @override Widget build(BuildContext context) { - final identityProviders = controller.identityProviders; - final errorText = controller.error; - // #Pangea - // final publicHomeserver = controller.cachedHomeservers?.singleWhereOrNull( - // (homeserver) => - // homeserver.name == - // controller.homeserverController.text.trim().toLowerCase(), - // ); - // final regLink = publicHomeserver?.regLink; - // Pangea# + final theme = Theme.of(context); + return LoginScaffold( // #Pangea // enforceMobileMode: Matrix.of(context).client.isLogged(), - // appBar: AppBar( - // titleSpacing: 12, - // automaticallyImplyLeading: false, - // surfaceTintColor: Theme.of(context).colorScheme.background, - // title: HomeserverAppBar(controller: controller), - // ), + // appBar: controller.widget.addMultiAccount + // ? AppBar( + // centerTitle: true, + // title: Text(L10n.of(context)!.addAccount), + // ) + // : null, appBar: AppBar( centerTitle: true, title: Text( @@ -43,6 +34,7 @@ class HomeserverPickerView extends StatelessWidget { ), // Pangea# body: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // display a prominent banner to import session for TOR browser // users. This feature is just some UX sugar as TOR users are @@ -58,7 +50,7 @@ class HomeserverPickerView extends StatelessWidget { // clipBehavior: Clip.hardEdge, // borderRadius: // const BorderRadius.vertical(bottom: Radius.circular(8)), - // color: Theme.of(context).colorScheme.surface, + // color: theme.colorScheme.surface, // child: ListTile( // leading: const Icon(Icons.vpn_key), // title: Text(L10n.of(context)!.hydrateTor), @@ -68,20 +60,136 @@ class HomeserverPickerView extends StatelessWidget { // ), // ), // ), - // Pangea# + // if (MediaQuery.of(context).size.height > 512) + // ConstrainedBox( + // constraints: BoxConstraints( + // maxHeight: MediaQuery.of(context).size.height / 4, + // ), + // child: Image.asset( + // 'assets/banner_transparent.png', + // alignment: Alignment.center, + // repeat: ImageRepeat.repeat, + // ), + // ), + // Padding( + // padding: const EdgeInsets.all(32.0), + // child: TextField( + // onChanged: controller.tryCheckHomeserverActionWithCooldown, + // onEditingComplete: + // controller.tryCheckHomeserverActionWithoutCooldown, + // onSubmitted: controller.tryCheckHomeserverActionWithoutCooldown, + // onTap: controller.tryCheckHomeserverActionWithCooldown, + // controller: controller.homeserverController, + // autocorrect: false, + // keyboardType: TextInputType.url, + // decoration: InputDecoration( + // prefixIcon: controller.isLoading + // ? Container( + // width: 16, + // height: 16, + // alignment: Alignment.center, + // child: const SizedBox( + // width: 16, + // height: 16, + // child: CircularProgressIndicator.adaptive( + // strokeWidth: 2, + // ), + // ), + // ) + // : const Icon(Icons.search_outlined), + // filled: false, + // border: OutlineInputBorder( + // borderRadius: BorderRadius.circular(AppConfig.borderRadius), + // ), + // hintText: AppConfig.defaultHomeserver, + // labelText: L10n.of(context)!.homeserver, + // errorText: controller.error, + // suffixIcon: IconButton( + // onPressed: () { + // showDialog( + // context: context, + // builder: (context) => AlertDialog.adaptive( + // title: Text(L10n.of(context)!.whatIsAHomeserver), + // content: Linkify( + // text: L10n.of(context)!.homeserverDescription, + // ), + // actions: [ + // TextButton( + // onPressed: () => launchUrl( + // Uri.https('servers.joinmatrix.org'), + // ), + // child: Text( + // L10n.of(context)!.discoverHomeservers, + // ), + // ), + // TextButton( + // onPressed: Navigator.of(context).pop, + // child: Text(L10n.of(context)!.close), + // ), + // ], + // ), + // ); + // }, + // icon: const Icon(Icons.info_outlined), + // ), + // ), + // ), + // ), + // if (MediaQuery.of(context).size.height > 512) const Spacer(), + // ListView( + // shrinkWrap: true, + // padding: const EdgeInsets.symmetric( + // horizontal: 32.0, + // vertical: 32.0, + // ), + // children: [ + // TextButton( + // style: TextButton.styleFrom( + // textStyle: theme.textTheme.labelMedium, + // foregroundColor: theme.colorScheme.secondary, + // ), + // onPressed: controller.isLoggingIn || controller.isLoading + // ? null + // : controller.restoreBackup, + // child: Text(L10n.of(context)!.hydrate), + // ), + // if (controller.supportsPasswordLogin && controller.supportsSso) + // TextButton( + // style: TextButton.styleFrom( + // foregroundColor: theme.colorScheme.secondary, + // textStyle: theme.textTheme.labelMedium, + // ), + // onPressed: controller.isLoggingIn || controller.isLoading + // ? null + // : controller.login, + // child: Text(L10n.of(context)!.loginWithMatrixId), + // ), + // const SizedBox(height: 8.0), + // if (controller.supportsPasswordLogin || controller.supportsSso) + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // backgroundColor: theme.colorScheme.primary, + // foregroundColor: theme.colorScheme.onPrimary, + // ), + // onPressed: controller.isLoggingIn || controller.isLoading + // ? null + // : controller.supportsSso + // ? controller.ssoLoginAction + // : controller.login, + // child: Text(L10n.of(context)!.next), + // ), + // ], + // ), Expanded( child: controller.isLoading - // #Pangea - // ? const Center(child: CircularProgressIndicator.adaptive()) ? const Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.black), ), ) - // Pangea# : ListView( children: [ - if (errorText != null) ...[ + if (controller.error != null) ...[ const SizedBox(height: 12), const Center( child: Icon( @@ -93,7 +201,7 @@ class HomeserverPickerView extends StatelessWidget { const SizedBox(height: 12), Center( child: Text( - errorText, + controller.error!, textAlign: TextAlign.center, style: TextStyle( color: Theme.of(context).colorScheme.error, @@ -101,38 +209,11 @@ class HomeserverPickerView extends StatelessWidget { ), ), ), - // #Pangea - // Center( - // child: Text( - // L10n.of(context)! - // .pleaseTryAgainLaterOrChooseDifferentServer, - // textAlign: TextAlign.center, - // style: TextStyle( - // color: Theme.of(context).colorScheme.error, - // fontSize: 12, - // ), - // ), - // ), - // Pangea# const SizedBox(height: 36), ] else - // #Pangea const SignupButtons(), - // Padding( - // padding: const EdgeInsets.only( - // top: 0.0, - // right: 8.0, - // left: 8.0, - // bottom: 16.0, - // ), - // child: Image.asset( - // 'assets/banner_transparent.png', - // ), - // ), - // Pangea# - if (identityProviders != null) ...[ - // #Pangea - ...identityProviders.map( + if (controller.identityProviders != null) ...[ + ...controller.identityProviders!.map( (provider) => Padding( padding: const EdgeInsets.all(12.0), child: Hero( @@ -145,43 +226,7 @@ class HomeserverPickerView extends StatelessWidget { ), ), ), - // ...identityProviders.map( - // (provider) => _LoginButton( - // icon: provider.icon == null - // ? const Icon( - // Icons.open_in_new_outlined, - // size: 16, - // ) - // : Material( - // borderRadius: BorderRadius.circular( - // AppConfig.borderRadius, - // ), - // clipBehavior: Clip.hardEdge, - // child: MxcImage( - // placeholder: (_) => const Icon( - // Icons.open_in_new_outlined, - // size: 16, - // ), - // uri: Uri.parse(provider.icon!), - // width: 24, - // height: 24, - // isThumbnail: false, - // //isThumbnail: false, - // ), - // ), - // label: L10n.of(context)!.signInWith( - // provider.name ?? - // provider.brand ?? - // L10n.of(context)!.singlesignon, - // ), - // onPressed: () => - // controller.ssoLoginAction(provider.id), - // ), - // ), - // ], - // Pangea# if (controller.supportsPasswordLogin) - // #Pangea Padding( padding: const EdgeInsets.all(12.0), child: Hero( @@ -205,80 +250,13 @@ class HomeserverPickerView extends StatelessWidget { ), ), ), - // _LoginButton( - // onPressed: controller.login, - // label: L10n.of(context)!.signInWithPassword, - // icon: const Icon(Icons.lock_open_outlined, size: 16), - // ), - // if (regLink != null) - // _LoginButton( - // onPressed: () => launchUrlString(regLink), - // icon: const Icon( - // Icons.open_in_new_outlined, - // size: 16, - // ), - // label: L10n.of(context)!.register, - // ), - // _LoginButton( - // onPressed: controller.restoreBackup, - // label: L10n.of(context)!.hydrate, - // withBorder: false, - // ), - // const SizedBox(height: 16), - // Pangea# ], ], ), ), + // Pangea# ], ), ); } } - -class _LoginButton extends StatelessWidget { - final Widget? icon; - final String label; - final void Function() onPressed; - final bool withBorder; - - const _LoginButton({ - this.icon, - required this.label, - required this.onPressed, - this.withBorder = true, - }); - - @override - Widget build(BuildContext context) { - final icon = this.icon; - return Container( - margin: const EdgeInsets.only(bottom: 12), - padding: const EdgeInsets.symmetric(horizontal: 16), - alignment: Alignment.center, - child: SizedBox( - width: double.infinity, - child: OutlinedButton.icon( - style: OutlinedButton.styleFrom( - side: FluffyThemes.isColumnMode(context) - ? BorderSide.none - : BorderSide( - color: Theme.of(context).colorScheme.outlineVariant, - width: 1, - ), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(99), - ), - foregroundColor: Theme.of(context).colorScheme.onSurface, - backgroundColor: withBorder - ? Theme.of(context).colorScheme.surface - : Colors.transparent, - ), - onPressed: onPressed, - label: Text(label), - icon: icon ?? const SizedBox.shrink(), - ), - ), - ); - } -} diff --git a/lib/pages/homeserver_picker/public_homeserver.dart b/lib/pages/homeserver_picker/public_homeserver.dart deleted file mode 100644 index 4eef2aa56..000000000 --- a/lib/pages/homeserver_picker/public_homeserver.dart +++ /dev/null @@ -1,73 +0,0 @@ -class PublicHomeserver { - final String name; - final String? clientDomain; - final String? isp; - final String? staffJur; - final bool? usingVanillaReg; - final String? description; - final String? regMethod; - final String? regLink; - final String? software; - final String? version; - final bool? captcha; - final bool? email; - final List? languages; - final List? features; - final int? onlineStatus; - final String? serverDomain; - final int? verStatus; - final int? roomDirectory; - final bool? slidingSync; - final bool? ipv6; - - const PublicHomeserver({ - required this.name, - this.clientDomain, - this.isp, - this.staffJur, - this.usingVanillaReg, - this.description, - this.regMethod, - this.regLink, - this.software, - this.version, - this.captcha, - this.email, - this.languages, - this.features, - this.onlineStatus, - this.serverDomain, - this.verStatus, - this.roomDirectory, - this.slidingSync, - this.ipv6, - }); - - factory PublicHomeserver.fromJson(Map json) => - PublicHomeserver( - name: json['name'], - clientDomain: json['client_domain'], - isp: json['isp'], - staffJur: json['staff_jur'], - usingVanillaReg: json['using_vanilla_reg'], - description: json['description'], - regMethod: json['reg_method'], - regLink: json['reg_link'], - software: json['software'], - version: json['version'], - captcha: json['captcha'], - email: json['email'], - languages: json['languages'] == null - ? null - : List.from(json['languages']), - features: json['features'] == null - ? null - : List.from(json['features']), - onlineStatus: json['online_status'], - serverDomain: json['server_domain'], - verStatus: json['ver_status'], - roomDirectory: json['room_directory'], - slidingSync: json['sliding_sync'], - ipv6: json['ipv6'], - ); -} diff --git a/lib/pages/invitation_selection/invitation_selection.dart b/lib/pages/invitation_selection/invitation_selection.dart index e59e03819..761f43271 100644 --- a/lib/pages/invitation_selection/invitation_selection.dart +++ b/lib/pages/invitation_selection/invitation_selection.dart @@ -182,7 +182,10 @@ class InvitationSelectionController extends State { if (success.error == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text(L10n.of(context)!.contactHasBeenInvitedToTheGroup), + // #Pangea + // content: Text(L10n.of(context)!.contactHasBeenInvitedToTheGroup), + content: Text(L10n.of(context)!.contactHasBeenInvitedToTheChat), + // Pangea# ), ); } diff --git a/lib/pages/invitation_selection/invitation_selection_view.dart b/lib/pages/invitation_selection/invitation_selection_view.dart index a776cccb0..524005208 100644 --- a/lib/pages/invitation_selection/invitation_selection_view.dart +++ b/lib/pages/invitation_selection/invitation_selection_view.dart @@ -30,6 +30,7 @@ class InvitationSelectionView extends StatelessWidget { // #Pangea // final groupName = room.name.isEmpty ? L10n.of(context)!.group : room.name; // Pangea# + final theme = Theme.of(context); return Scaffold( appBar: AppBar( // #Pangea @@ -52,6 +53,16 @@ class InvitationSelectionView extends StatelessWidget { child: TextField( textInputAction: TextInputAction.search, decoration: InputDecoration( + filled: true, + fillColor: theme.colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(99), + ), + hintStyle: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontWeight: FontWeight.normal, + ), // #Pangea hintText: controller.mode == InvitationSelectionMode.admin ? L10n.of(context)!.inviteUsersFromPangea @@ -189,6 +200,8 @@ class _InviteContactListTile extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return Opacity( opacity: isMember ? 0.5 : 1, child: ListTile( @@ -207,7 +220,7 @@ class _InviteContactListTile extends StatelessWidget { maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), onTap: isMember ? null : onTap, diff --git a/lib/pages/key_verification/key_verification_dialog.dart b/lib/pages/key_verification/key_verification_dialog.dart index 99d082a76..b4e5a91ae 100644 --- a/lib/pages/key_verification/key_verification_dialog.dart +++ b/lib/pages/key_verification/key_verification_dialog.dart @@ -94,6 +94,8 @@ class KeyVerificationPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + User? user; final directChatId = widget.request.client.getDirectChatFromUserId(widget.request.userId); @@ -139,10 +141,8 @@ class KeyVerificationPageState extends State { obscureText: true, decoration: InputDecoration( hintText: L10n.of(context)!.passphraseOrKey, - prefixStyle: - TextStyle(color: Theme.of(context).colorScheme.primary), - suffixStyle: - TextStyle(color: Theme.of(context).colorScheme.primary), + prefixStyle: TextStyle(color: theme.colorScheme.primary), + suffixStyle: TextStyle(color: theme.colorScheme.primary), border: const OutlineInputBorder(), ), ), diff --git a/lib/pages/login/login_view.dart b/lib/pages/login/login_view.dart index 818dd06b4..e4a22d76d 100644 --- a/lib/pages/login/login_view.dart +++ b/lib/pages/login/login_view.dart @@ -11,6 +11,8 @@ class LoginView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + // #Pangea // final homeserver = Matrix.of(context) // .getLoginClient() @@ -19,10 +21,6 @@ class LoginView extends StatelessWidget { // .replaceFirst('https://', ''); // final title = L10n.of(context)!.logInTo(homeserver); // final titleParts = title.split(homeserver); - - // final textFieldFillColor = FluffyThemes.isColumnMode(context) - // ? Theme.of(context).colorScheme.background - // : Theme.of(context).colorScheme.surfaceVariant; // Pangea# return LoginScaffold( @@ -99,19 +97,14 @@ class LoginView extends StatelessWidget { errorText: controller.usernameError, // #Pangea // errorStyle: const TextStyle(color: Colors.orange), + // hintText: '@username:localpart', errorStyle: TextStyle( color: Theme.of(context).textTheme.bodyMedium?.color, fontSize: 14, ), - // Pangea# hintText: L10n.of(context)!.emailOrUsername, - // #Pangea - // fillColor: textFieldFillColor, - fillColor: Theme.of(context) - .colorScheme - .surface - .withOpacity(0.75), // Pangea# + labelText: L10n.of(context)!.emailOrUsername, ), ), ), @@ -131,13 +124,10 @@ class LoginView extends StatelessWidget { prefixIcon: const Icon(Icons.lock_outlined), errorText: controller.passwordError, // #Pangea - // errorStyle: const TextStyle(color: Colors.orange), errorStyle: TextStyle( color: Theme.of(context).textTheme.bodyMedium?.color, fontSize: 14, ), - // fillColor: textFieldFillColor, - // prevent enter key from clicking show password button suffixIcon: MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( @@ -151,6 +141,7 @@ class LoginView extends StatelessWidget { ), ), ), + // errorStyle: const TextStyle(color: Colors.orange), // suffixIcon: IconButton( // onPressed: controller.toggleShowPassword, // icon: Icon( @@ -161,13 +152,8 @@ class LoginView extends StatelessWidget { // ), // ), // Pangea# - hintText: L10n.of(context)!.password, - // #Pangea - fillColor: Theme.of(context) - .colorScheme - .surface - .withOpacity(0.75), - // Pangea# + hintText: '******', + labelText: L10n.of(context)!.password, ), ), ), @@ -182,14 +168,13 @@ class LoginView extends StatelessWidget { ? const LinearProgressIndicator() : Text(L10n.of(context)!.login), ), - // child: ElevatedButton.icon( + // child: ElevatedButton( // style: ElevatedButton.styleFrom( - // backgroundColor: Theme.of(context).colorScheme.primary, - // foregroundColor: Theme.of(context).colorScheme.onPrimary, + // backgroundColor: theme.colorScheme.primary, + // foregroundColor: theme.colorScheme.onPrimary, // ), // onPressed: controller.loading ? null : controller.login, - // icon: const Icon(Icons.login_outlined), - // label: controller.loading + // child: controller.loading // ? const LinearProgressIndicator() // : Text(L10n.of(context)!.login), // ), @@ -235,15 +220,14 @@ class LoginView extends StatelessWidget { ElevatedButton.styleFrom(foregroundColor: Colors.red), child: Text(L10n.of(context)!.passwordForgotten), ), - // child: TextButton.icon( + // child: TextButton( // onPressed: controller.loading // ? () {} // : controller.passwordForgotten, // style: TextButton.styleFrom( - // foregroundColor: Theme.of(context).colorScheme.error, + // foregroundColor: theme.colorScheme.error, // ), - // icon: const Icon(Icons.safety_check_outlined), - // label: Text(L10n.of(context)!.passwordForgotten), + // child: Text(L10n.of(context)!.passwordForgotten), // ), // Pangea# ), diff --git a/lib/pages/new_group/new_group.dart b/lib/pages/new_group/new_group.dart index aa4a2504b..aa3c54708 100644 --- a/lib/pages/new_group/new_group.dart +++ b/lib/pages/new_group/new_group.dart @@ -35,8 +35,6 @@ class NewGroup extends StatefulWidget { class NewGroupController extends State { TextEditingController nameController = TextEditingController(); - TextEditingController topicController = TextEditingController(); - bool publicGroup = false; bool groupCanBeFound = true; @@ -132,6 +130,7 @@ class NewGroupController extends State { } } } + // Pangea# final roomId = await client.createGroupChat( // #Pangea @@ -140,24 +139,6 @@ class NewGroupController extends State { // preset: publicGroup // ? sdk.CreateRoomPreset.publicChat // : sdk.CreateRoomPreset.privateChat, - // groupName: nameController.text.isNotEmpty ? nameController.text : null, - // initialState: [ - // if (topicController.text.isNotEmpty) - // sdk.StateEvent( - // type: sdk.EventTypes.RoomTopic, - // content: {'topic': topicController.text}, - // ), - // if (avatar != null) - // sdk.StateEvent( - // type: sdk.EventTypes.RoomAvatar, - // content: {'url': avatarUrl.toString()}, - // ), - // ], - initialState: [ - if (addConversationBotKey.currentState?.addBot ?? false) - addConversationBotKey.currentState!.botOptions.toStateEvent, - ], - groupName: nameController.text, preset: sdk.CreateRoomPreset.publicChat, powerLevelContentOverride: await ClassChatPowerLevels.powerLevelOverrideForClassChat( @@ -169,6 +150,18 @@ class NewGroupController extends State { BotName.byEnvironment, ], // Pangea# + groupName: nameController.text.isNotEmpty ? nameController.text : null, + initialState: [ + if (avatar != null) + sdk.StateEvent( + type: sdk.EventTypes.RoomAvatar, + content: {'url': avatarUrl.toString()}, + ), + // #Pangea + if (addConversationBotKey.currentState?.addBot ?? false) + addConversationBotKey.currentState!.botOptions.toStateEvent, + // Pangea# + ], ); if (!mounted) return; if (publicGroup && groupCanBeFound) { diff --git a/lib/pages/new_group/new_group_view.dart b/lib/pages/new_group/new_group_view.dart index 84bfbfbc5..6dfcec212 100644 --- a/lib/pages/new_group/new_group_view.dart +++ b/lib/pages/new_group/new_group_view.dart @@ -16,6 +16,8 @@ class NewGroupView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final avatar = controller.avatar; final error = controller.error; return Scaffold( @@ -25,7 +27,10 @@ class NewGroupView extends StatelessWidget { onPressed: controller.loading ? null : Navigator.of(context).pop, ), ), - title: Text(L10n.of(context)!.createGroup), + // #Pangea + // title: Text(L10n.of(context)!.createGroup), + title: Text(L10n.of(context)!.createChat), + // Pangea# ), // #Pangea floatingActionButton: FloatingActionButton.extended( @@ -41,61 +46,46 @@ class NewGroupView extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 16), + InkWell( + borderRadius: BorderRadius.circular(90), + onTap: controller.loading ? null : controller.selectPhoto, + child: CircleAvatar( + radius: Avatar.defaultSize, + child: avatar == null + ? const Icon(Icons.add_a_photo_outlined) + : ClipRRect( + borderRadius: BorderRadius.circular(90), + child: Image.memory( + avatar, + width: Avatar.defaultSize, + height: Avatar.defaultSize, + fit: BoxFit.cover, + ), + ), + ), + ), + const SizedBox(height: 32), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Row( - children: [ - InkWell( - borderRadius: BorderRadius.circular(90), - onTap: controller.loading ? null : controller.selectPhoto, - child: CircleAvatar( - radius: Avatar.defaultSize / 2, - child: avatar == null - ? const Icon(Icons.camera_alt_outlined) - : ClipRRect( - borderRadius: BorderRadius.circular(90), - child: Image.memory( - avatar, - width: Avatar.defaultSize, - height: Avatar.defaultSize, - fit: BoxFit.cover, - ), - ), - ), - ), - const SizedBox(width: 16), - Expanded( - child: TextField( - // #Pangea - maxLength: 64, - // Pangea# - controller: controller.nameController, - autocorrect: false, - readOnly: controller.loading, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.people_outlined), - hintText: L10n.of(context)!.groupName, - ), - ), - ), - ], + child: TextField( + // #Pangea + maxLength: 64, + // Pangea# + autofocus: true, + controller: controller.nameController, + autocorrect: false, + readOnly: controller.loading, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.people_outlined), + // #Pangea + // labelText: L10n.of(context)!.groupName, + labelText: L10n.of(context)!.chatName, + // Pangea# + ), ), ), const SizedBox(height: 16), // #Pangea - // Padding( - // padding: const EdgeInsets.symmetric(horizontal: 16.0), - // child: TextField( - // controller: controller.topicController, - // minLines: 4, - // maxLines: 4, - // maxLength: 255, - // readOnly: controller.loading, - // decoration: InputDecoration( - // hintText: L10n.of(context)!.addChatDescription, - // ), - // ), - // ), RoomCapacityButton( key: controller.addCapacityKey, ), @@ -109,7 +99,6 @@ class NewGroupView extends StatelessWidget { startOpen: true, activeSpaceId: controller.activeSpaceId, ), - // const SizedBox(height: 16), // SwitchListTile.adaptive( // secondary: const Icon(Icons.public_outlined), // title: Text(L10n.of(context)!.groupIsPublic), @@ -132,12 +121,12 @@ class NewGroupView extends StatelessWidget { // SwitchListTile.adaptive( // secondary: Icon( // Icons.lock_outlined, - // color: Theme.of(context).colorScheme.onSurface, + // color: theme.colorScheme.onSurface, // ), // title: Text( // L10n.of(context)!.enableEncryption, // style: TextStyle( - // color: Theme.of(context).colorScheme.onSurface, + // color: theme.colorScheme.onSurface, // ), // ), // value: !controller.publicGroup, @@ -148,24 +137,20 @@ class NewGroupView extends StatelessWidget { // child: SizedBox( // width: double.infinity, // child: ElevatedButton( - // style: ElevatedButton.styleFrom( - // foregroundColor: Theme.of(context).colorScheme.onPrimary, - // backgroundColor: Theme.of(context).colorScheme.primary, - // ), // onPressed: // controller.loading ? null : controller.submitAction, - // child: controller.loading - // ? const LinearProgressIndicator() - // : Row( - // children: [ - // Expanded( - // child: Text( - // L10n.of(context)!.createGroupAndInviteUsers, + // child: controller.loading + // ? const LinearProgressIndicator() + // : Row( + // children: [ + // Expanded( + // child: Text( + // L10n.of(context)!.createGroupAndInviteUsers, + // ), + // ), + // Icon(Icons.adaptive.arrow_forward_outlined), + // ], // ), - // ), - // Icon(Icons.adaptive.arrow_forward_outlined), - // ], - // ), // ), // ), // ), @@ -177,12 +162,12 @@ class NewGroupView extends StatelessWidget { : ListTile( leading: Icon( Icons.warning_outlined, - color: Theme.of(context).colorScheme.error, + color: theme.colorScheme.error, ), title: Text( error.toLocalizedString(context), style: TextStyle( - color: Theme.of(context).colorScheme.error, + color: theme.colorScheme.error, ), ), ), diff --git a/lib/pages/new_private_chat/new_private_chat_view.dart b/lib/pages/new_private_chat/new_private_chat_view.dart index 80cc725fc..024e52bc7 100644 --- a/lib/pages/new_private_chat/new_private_chat_view.dart +++ b/lib/pages/new_private_chat/new_private_chat_view.dart @@ -20,13 +20,15 @@ class NewPrivateChatView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final searchResponse = controller.searchResponse; return Scaffold( appBar: AppBar( scrolledUnderElevation: 0, leading: const Center(child: BackButton()), title: Text(L10n.of(context)!.newChat), - backgroundColor: Theme.of(context).scaffoldBackgroundColor, + backgroundColor: theme.scaffoldBackgroundColor, actions: [ TextButton( onPressed: @@ -50,6 +52,16 @@ class NewPrivateChatView extends StatelessWidget { onChanged: controller.searchUsers, decoration: InputDecoration( hintText: L10n.of(context)!.searchForUsers, + filled: true, + fillColor: theme.colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(99), + ), + hintStyle: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontWeight: FontWeight.normal, + ), prefixIcon: searchResponse == null ? const Icon(Icons.search_outlined) : FutureBuilder( @@ -107,7 +119,7 @@ class NewPrivateChatView extends StatelessWidget { ], ), style: TextStyle( - color: Theme.of(context).colorScheme.onSurface, + color: theme.colorScheme.onSurface, fontSize: 13, ), ), @@ -115,10 +127,8 @@ class NewPrivateChatView extends StatelessWidget { const SizedBox(height: 8), ListTile( leading: CircleAvatar( - backgroundColor: - Theme.of(context).colorScheme.secondaryContainer, - foregroundColor: - Theme.of(context).colorScheme.onSecondaryContainer, + backgroundColor: theme.colorScheme.secondaryContainer, + foregroundColor: theme.colorScheme.onSecondaryContainer, child: Icon(Icons.adaptive.share_outlined), ), title: Text(L10n.of(context)!.shareInviteLink), @@ -126,22 +136,21 @@ class NewPrivateChatView extends StatelessWidget { ), ListTile( leading: CircleAvatar( - backgroundColor: - Theme.of(context).colorScheme.tertiaryContainer, - foregroundColor: - Theme.of(context).colorScheme.onTertiaryContainer, + backgroundColor: theme.colorScheme.tertiaryContainer, + foregroundColor: theme.colorScheme.onTertiaryContainer, child: const Icon(Icons.group_add_outlined), ), - title: Text(L10n.of(context)!.createGroup), + // #Pangea + // title: Text(L10n.of(context)!.createGroup), + title: Text(L10n.of(context)!.createChat), + // Pangea# onTap: () => context.go('/rooms/newgroup'), ), if (PlatformInfos.isMobile) ListTile( leading: CircleAvatar( - backgroundColor: - Theme.of(context).colorScheme.primaryContainer, - foregroundColor: - Theme.of(context).colorScheme.onPrimaryContainer, + backgroundColor: theme.colorScheme.primaryContainer, + foregroundColor: theme.colorScheme.onPrimaryContainer, child: const Icon(Icons.qr_code_scanner_outlined), ), title: Text(L10n.of(context)!.scanQrCode), @@ -156,8 +165,7 @@ class NewPrivateChatView extends StatelessWidget { borderRadius: BorderRadius.circular(12), elevation: 10, color: Colors.white, - shadowColor: - Theme.of(context).appBarTheme.shadowColor, + shadowColor: theme.appBarTheme.shadowColor, clipBehavior: Clip.hardEdge, child: Padding( padding: const EdgeInsets.all(8), @@ -167,12 +175,9 @@ class NewPrivateChatView extends StatelessWidget { decoration: PrettyQrDecoration( shape: PrettyQrSmoothSymbol( roundFactor: 1, - color: Theme.of(context).brightness == - Brightness.light - ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onPrimary, + color: theme.brightness == Brightness.light + ? theme.colorScheme.primary + : theme.colorScheme.onPrimary, ), ), ), @@ -196,7 +201,7 @@ class NewPrivateChatView extends StatelessWidget { error.toLocalizedString(context), textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context).colorScheme.error, + color: theme.colorScheme.error, ), ), const SizedBox(height: 12), @@ -225,7 +230,7 @@ class NewPrivateChatView extends StatelessWidget { controller.controller.text, ), style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), textAlign: TextAlign.center, ), diff --git a/lib/pages/new_space/new_space_view.dart b/lib/pages/new_space/new_space_view.dart index 7996def21..087218a48 100644 --- a/lib/pages/new_space/new_space_view.dart +++ b/lib/pages/new_space/new_space_view.dart @@ -1,4 +1,3 @@ -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/pages/class_settings/p_class_widgets/room_capacity_button.dart'; import 'package:fluffychat/pangea/widgets/class/add_space_toggles.dart'; import 'package:fluffychat/widgets/avatar.dart'; @@ -15,17 +14,9 @@ class NewSpaceView extends StatelessWidget { @override Widget build(BuildContext context) { - // #Pangea - final activeColor = Theme.of(context).brightness == Brightness.dark - ? AppConfig.primaryColorLight - : AppConfig.primaryColor; - // Pangea# final avatar = controller.avatar; return Scaffold( appBar: AppBar( - // #Pangea - centerTitle: true, - // Pangea# title: Text(L10n.of(context)!.createNewSpace), ), // #Pangea @@ -41,7 +32,58 @@ class NewSpaceView extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ + const SizedBox(height: 16), + InkWell( + borderRadius: BorderRadius.circular(90), + onTap: controller.loading ? null : controller.selectPhoto, + child: CircleAvatar( + radius: Avatar.defaultSize, + child: avatar == null + ? const Icon(Icons.add_a_photo_outlined) + : ClipRRect( + borderRadius: BorderRadius.circular(90), + child: Image.memory( + avatar, + width: Avatar.defaultSize, + height: Avatar.defaultSize, + fit: BoxFit.cover, + ), + ), + ), + ), + const SizedBox(height: 32), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: TextField( + autofocus: true, + controller: controller.nameController, + autocorrect: false, + readOnly: controller.loading, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.people_outlined), + labelText: L10n.of(context)!.spaceName, + // #Pangea + // errorText: controller.nameError, + // Pangea# + ), + ), + ), + const SizedBox(height: 16), // #Pangea + RoomCapacityButton( + key: controller.addCapacityKey, + spaceMode: true, + ), + AddToSpaceToggles( + key: controller.addToSpaceKey, + startOpen: true, + spaceMode: true, + ), + // SwitchListTile.adaptive( + // title: Text(L10n.of(context)!.spaceIsPublic), + // value: controller.publicGroup, + // onChanged: controller.setPublicGroup, + // ), // ListTile( // trailing: const Padding( // padding: EdgeInsets.symmetric(horizontal: 16.0), @@ -49,134 +91,11 @@ class NewSpaceView extends StatelessWidget { // ), // subtitle: Text(L10n.of(context)!.newSpaceDescription), // ), - // const SizedBox(height: 16), - // Pangea# - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - InkWell( - borderRadius: BorderRadius.circular(90), - onTap: controller.loading ? null : controller.selectPhoto, - child: CircleAvatar( - radius: Avatar.defaultSize / 2, - child: avatar == null - ? const Icon(Icons.camera_alt_outlined) - : ClipRRect( - borderRadius: BorderRadius.circular(90), - child: Image.memory( - avatar, - width: Avatar.defaultSize, - height: Avatar.defaultSize, - fit: BoxFit.cover, - ), - ), - ), - ), - const SizedBox(width: 16), - Expanded( - child: TextField( - // #Pangea - maxLength: 64, - // Pangea# - controller: controller.nameController, - autocorrect: false, - readOnly: controller.loading, - decoration: InputDecoration( - prefixIcon: const Icon(Icons.people_outlined), - hintText: L10n.of(context)!.spaceName, - // #Pangea - // errorText: controller.nameError, - // Pangea# - ), - ), - ), - ], - ), - ), - const SizedBox(height: 16), - // #Pangea - // Padding( - // padding: const EdgeInsets.symmetric(horizontal: 16.0), - // child: TextField( - // controller: controller.topicController, - // minLines: 4, - // maxLines: 4, - // maxLength: 255, - // readOnly: controller.loading, - // decoration: InputDecoration( - // hintText: L10n.of(context)!.addChatDescription, - // errorText: controller.topicError, - // ), - // ), - // ), - // const SizedBox(height: 16), - - RoomCapacityButton( - key: controller.addCapacityKey, - spaceMode: true, - ), - // commenting out language settings in spaces for now - // LanguageSettings( - // key: controller.languageSettingsKey, - // roomId: null, - // startOpen: true, - // initialSettings: - // Matrix.of(context).client.lastUpdatedLanguageSettings, - // ), - AddToSpaceToggles( - key: controller.addToSpaceKey, - startOpen: true, - spaceMode: true, - ), - // Commenting out pangea room rules for now - // if (controller.rulesEditorKey.currentState != null) - // RoomRulesEditor( - // key: controller.rulesEditorKey, - // roomId: null, - // startOpen: false, - // initialRules: controller.rulesEditorKey.currentState!.rules, - // ), - - // Commenting out pangea room rules for now - // if (controller.rulesEditorKey.currentState == null) - // FutureBuilder( - // future: Matrix.of(context).client.lastUpdatedRoomRules, - // builder: (context, snapshot) { - // if (snapshot.connectionState == ConnectionState.done) { - // return RoomRulesEditor( - // key: controller.rulesEditorKey, - // roomId: null, - // startOpen: false, - // initialRules: snapshot.data, - // ); - // } else { - // return const Padding( - // padding: EdgeInsets.all(16.0), - // child: Center( - // child: - // CircularProgressIndicator.adaptive(strokeWidth: 2), - // ), - // ); - // } - // }, - // ), - - // SwitchListTile.adaptive( - // title: Text(L10n.of(context)!.spaceIsPublic), - // value: controller.publicGroup, - // onChanged: controller.setPublicGroup, - // ), // Padding( // padding: const EdgeInsets.all(16.0), // child: SizedBox( // width: double.infinity, // child: ElevatedButton( - // style: ElevatedButton.styleFrom( - // foregroundColor: Theme.of(context).colorScheme.onPrimary, - // backgroundColor: Theme.of(context).colorScheme.primary, - // ), // onPressed: // controller.loading ? null : controller.submitAction, // child: controller.loading diff --git a/lib/pages/settings/settings.dart b/lib/pages/settings/settings.dart index 55b39fa3d..55ba7bf93 100644 --- a/lib/pages/settings/settings.dart +++ b/lib/pages/settings/settings.dart @@ -222,8 +222,6 @@ class SettingsController extends State { final client = Matrix.of(context).client; profileFuture ??= client.getProfileFromUserId( client.userID!, - cache: !profileUpdated, - getFromRooms: !profileUpdated, ); return SettingsView(this); } diff --git a/lib/pages/settings/settings_view.dart b/lib/pages/settings/settings_view.dart index c7e9d6e64..286b5d8e9 100644 --- a/lib/pages/settings/settings_view.dart +++ b/lib/pages/settings/settings_view.dart @@ -8,7 +8,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; -import 'package:package_info_plus/package_info_plus.dart'; //adding to check app version +import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'settings.dart'; @@ -20,7 +20,7 @@ class SettingsView extends StatelessWidget { // #Pangea Future getAppVersion(BuildContext context) async { - final PackageInfo packageInfo = await PackageInfo.fromPlatform(); + final packageInfo = await PackageInfo.fromPlatform(); return L10n.of(context)! .versionText(packageInfo.version, packageInfo.buildNumber); } @@ -28,9 +28,8 @@ class SettingsView extends StatelessWidget { @override Widget build(BuildContext context) { - // #Pangea - // final showChatBackupBanner = controller.showChatBackupBanner; - // Pangea# + final theme = Theme.of(context); + final showChatBackupBanner = controller.showChatBackupBanner; return Scaffold( appBar: AppBar( leading: Center( @@ -39,16 +38,9 @@ class SettingsView extends StatelessWidget { ), ), title: Text(L10n.of(context)!.settings), - actions: [ - TextButton.icon( - onPressed: controller.logoutAction, - label: Text(L10n.of(context)!.logout), - icon: const Icon(Icons.logout_outlined), - ), - ], ), body: ListTileTheme( - iconColor: Theme.of(context).colorScheme.onSurface, + iconColor: theme.colorScheme.onSurface, child: ListView( key: const Key('SettingsListViewContent'), children: [ @@ -66,32 +58,17 @@ class SettingsView extends StatelessWidget { padding: const EdgeInsets.all(32.0), child: Stack( children: [ - Material( - elevation: Theme.of(context) - .appBarTheme - .scrolledUnderElevation ?? - 4, - shadowColor: - Theme.of(context).appBarTheme.shadowColor, - shape: RoundedRectangleBorder( - side: BorderSide( - color: Theme.of(context).dividerColor, - ), - borderRadius: BorderRadius.circular( - Avatar.defaultSize * 2.5, - ), - ), - child: Avatar( - mxContent: profile?.avatarUrl, - name: displayname, - size: Avatar.defaultSize * 2.5, - ), + Avatar( + mxContent: profile?.avatarUrl, + name: displayname, + size: Avatar.defaultSize * 2.5, ), if (profile != null) Positioned( bottom: 0, right: 0, child: FloatingActionButton.small( + elevation: 2, onPressed: controller.setAvatarAction, heroTag: null, child: const Icon(Icons.camera_alt_outlined), @@ -112,14 +89,15 @@ class SettingsView extends StatelessWidget { size: 16, ), style: TextButton.styleFrom( - foregroundColor: - Theme.of(context).colorScheme.onSurface, + foregroundColor: theme.colorScheme.onSurface, ), label: Text( displayname, maxLines: 1, overflow: TextOverflow.ellipsis, - // style: const TextStyle(fontSize: 18), + style: const TextStyle( + fontSize: 18, + ), ), ), TextButton.icon( @@ -129,8 +107,7 @@ class SettingsView extends StatelessWidget { size: 14, ), style: TextButton.styleFrom( - foregroundColor: - Theme.of(context).colorScheme.secondary, + foregroundColor: theme.colorScheme.secondary, ), label: Text( mxid, @@ -147,10 +124,7 @@ class SettingsView extends StatelessWidget { }, ), // #Pangea - // Divider( - // height: 1, - // color: Theme.of(context).dividerColor, - // ), + // Divider(color: theme.dividerColor), // if (showChatBackupBanner == null) // ListTile( // leading: const Icon(Icons.backup_outlined), @@ -166,60 +140,47 @@ class SettingsView extends StatelessWidget { // onChanged: controller.firstRunBootstrapAction, // ), // Divider( - // height: 1, - // color: Theme.of(context).dividerColor, + // color: theme.dividerColor, // ), // Pangea# ListTile( leading: const Icon(Icons.format_paint_outlined), title: Text(L10n.of(context)!.changeTheme), onTap: () => context.go('/rooms/settings/style'), - trailing: const Icon(Icons.chevron_right_outlined), ), ListTile( leading: const Icon(Icons.notifications_outlined), title: Text(L10n.of(context)!.notifications), onTap: () => context.go('/rooms/settings/notifications'), - trailing: const Icon(Icons.chevron_right_outlined), ), ListTile( leading: const Icon(Icons.devices_outlined), title: Text(L10n.of(context)!.devices), onTap: () => context.go('/rooms/settings/devices'), - trailing: const Icon(Icons.chevron_right_outlined), ), ListTile( leading: const Icon(Icons.forum_outlined), title: Text(L10n.of(context)!.chat), onTap: () => context.go('/rooms/settings/chat'), - trailing: const Icon(Icons.chevron_right_outlined), ), // #Pangea ListTile( leading: const Icon(Icons.account_circle_outlined), title: Text(L10n.of(context)!.subscriptionManagement), onTap: () => context.go('/rooms/settings/subscription'), - trailing: const Icon( - Icons.chevron_right_outlined, - ), ), ListTile( leading: const Icon(Icons.psychology_outlined), title: Text(L10n.of(context)!.learningSettings), onTap: () => context.go('/rooms/settings/learning'), - trailing: const Icon(Icons.chevron_right_outlined), ), // Pangea# ListTile( leading: const Icon(Icons.shield_outlined), title: Text(L10n.of(context)!.security), onTap: () => context.go('/rooms/settings/security'), - trailing: const Icon(Icons.chevron_right_outlined), - ), - Divider( - height: 1, - color: Theme.of(context).dividerColor, ), + Divider(color: theme.dividerColor), ListTile( leading: const Icon(Icons.help_outline_outlined), title: Text(L10n.of(context)!.help), @@ -229,7 +190,7 @@ class SettingsView extends StatelessWidget { await showFutureLoadingDialog( context: context, future: () async { - final String roomId = + final roomId = await Matrix.of(context).client.startDirectChat( Environment.supportUserId, enableEncryption: false, @@ -239,20 +200,17 @@ class SettingsView extends StatelessWidget { ); }, // Pangea# - trailing: const Icon(Icons.open_in_new_outlined), ), ListTile( leading: const Icon(Icons.shield_sharp), title: Text(L10n.of(context)!.privacy), onTap: () => launchUrlString(AppConfig.privacyUrl), - trailing: const Icon(Icons.open_in_new_outlined), ), // #Pangea // ListTile( // leading: const Icon(Icons.info_outline_rounded), // title: Text(L10n.of(context)!.about), // onTap: () => PlatformInfos.showDialog(context), - // trailing: const Icon(Icons.chevron_right_outlined), // ), ListTile( leading: const Icon(Icons.shield_outlined), @@ -290,6 +248,12 @@ class SettingsView extends StatelessWidget { title: Text(L10n.of(context)!.connectedToStaging), ), // Pangea# + Divider(color: theme.dividerColor), + ListTile( + leading: const Icon(Icons.logout_outlined), + title: Text(L10n.of(context)!.logout), + onTap: controller.logoutAction, + ), ], ), ), diff --git a/lib/pages/settings_3pid/settings_3pid_view.dart b/lib/pages/settings_3pid/settings_3pid_view.dart index d54f194c5..72ee3f492 100644 --- a/lib/pages/settings_3pid/settings_3pid_view.dart +++ b/lib/pages/settings_3pid/settings_3pid_view.dart @@ -12,6 +12,8 @@ class Settings3PidView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + controller.request ??= Matrix.of(context).client.getAccount3PIDs(); return Scaffold( appBar: AppBar( @@ -51,7 +53,7 @@ class Settings3PidView extends StatelessWidget { children: [ ListTile( leading: CircleAvatar( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, + backgroundColor: theme.scaffoldBackgroundColor, foregroundColor: identifier.isEmpty ? Colors.orange : Colors.grey, child: Icon( @@ -67,14 +69,13 @@ class Settings3PidView extends StatelessWidget { .withTheseAddressesRecoveryDescription, ), ), - const Divider(height: 1), + const Divider(), Expanded( child: ListView.builder( itemCount: identifier.length, itemBuilder: (BuildContext context, int i) => ListTile( leading: CircleAvatar( - backgroundColor: - Theme.of(context).scaffoldBackgroundColor, + backgroundColor: theme.scaffoldBackgroundColor, foregroundColor: Colors.grey, child: Icon(identifier[i].iconData), ), diff --git a/lib/pages/settings_chat/settings_chat_view.dart b/lib/pages/settings_chat/settings_chat_view.dart index 25a4dd0a5..c549237d8 100644 --- a/lib/pages/settings_chat/settings_chat_view.dart +++ b/lib/pages/settings_chat/settings_chat_view.dart @@ -13,10 +13,12 @@ class SettingsChatView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return Scaffold( appBar: AppBar(title: Text(L10n.of(context)!.chat)), body: ListTileTheme( - iconColor: Theme.of(context).textTheme.bodyLarge!.color, + iconColor: theme.textTheme.bodyLarge!.color, child: MaxWidthBody( child: Column( children: [ @@ -71,15 +73,12 @@ class SettingsChatView extends StatelessWidget { defaultValue: AppConfig.swipeRightToLeftToReply, ), // #Pangea - // Divider( - // height: 1, - // color: Theme.of(context).dividerColor, - // ), + // Divider(color: theme.dividerColor), // ListTile( // title: Text( // L10n.of(context)!.customEmojisAndStickers, // style: TextStyle( - // color: Theme.of(context).colorScheme.secondary, + // color: theme.colorScheme.secondary, // fontWeight: FontWeight.bold, // ), // ), @@ -93,15 +92,12 @@ class SettingsChatView extends StatelessWidget { // child: Icon(Icons.chevron_right_outlined), // ), // ), - // Divider( - // height: 1, - // color: Theme.of(context).dividerColor, - // ), + // Divider(color: theme.dividerColor), // ListTile( // title: Text( // L10n.of(context)!.calls, // style: TextStyle( - // color: Theme.of(context).colorScheme.secondary, + // color: theme.colorScheme.secondary, // fontWeight: FontWeight.bold, // ), // ), diff --git a/lib/pages/settings_emotes/import_archive_dialog.dart b/lib/pages/settings_emotes/import_archive_dialog.dart index 0ed5bb21f..5c6361577 100644 --- a/lib/pages/settings_emotes/import_archive_dialog.dart +++ b/lib/pages/settings_emotes/import_archive_dialog.dart @@ -231,6 +231,8 @@ class _EmojiImportPreviewState extends State<_EmojiImportPreview> { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + // TODO: support Lottie here as well ... final controller = TextEditingController(text: widget.entry.value); @@ -281,11 +283,11 @@ class _EmojiImportPreviewState extends State<_EmojiImportPreview> { suffixText: ':', border: const OutlineInputBorder(), prefixStyle: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), suffixStyle: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -314,6 +316,8 @@ class _ImageFileError extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return SizedBox.square( dimension: 64, child: Tooltip( @@ -327,7 +331,7 @@ class _ImageFileError extends StatelessWidget { Text( L10n.of(context)!.notAnImage, textAlign: TextAlign.center, - style: Theme.of(context).textTheme.labelSmall, + style: theme.textTheme.labelSmall, ), ], ), diff --git a/lib/pages/settings_emotes/settings_emotes.dart b/lib/pages/settings_emotes/settings_emotes.dart index 2ef905b17..b90432f56 100644 --- a/lib/pages/settings_emotes/settings_emotes.dart +++ b/lib/pages/settings_emotes/settings_emotes.dart @@ -1,27 +1,25 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:archive/archive.dart' + if (dart.library.io) 'package:archive/archive_io.dart'; import 'package:collection/collection.dart'; import 'package:file_picker/file_picker.dart'; +import 'package:fluffychat/utils/client_manager.dart'; +import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart'; +import 'package:fluffychat/widgets/app_lock.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:go_router/go_router.dart'; import 'package:http/http.dart' hide Client; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/utils/client_manager.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart'; -import 'package:fluffychat/widgets/app_lock.dart'; import '../../widgets/matrix.dart'; import 'import_archive_dialog.dart'; import 'settings_emotes_view.dart'; -import 'package:archive/archive.dart' - if (dart.library.io) 'package:archive/archive_io.dart'; - class EmotesSettings extends StatefulWidget { const EmotesSettings({super.key}); @@ -330,8 +328,11 @@ class EmotesSettingsController extends State { for (final entry in pack.images.entries) { final emote = entry.value; final name = entry.key; - final url = emote.url.getDownloadLink(client); - final response = await get(url); + final url = await emote.url.getDownloadUri(client); + final response = await get( + url, + headers: {'authorization': 'Bearer ${client.accessToken}'}, + ); archive.addFile( ArchiveFile( diff --git a/lib/pages/settings_emotes/settings_emotes_view.dart b/lib/pages/settings_emotes/settings_emotes_view.dart index 7e72cd464..1337873a2 100644 --- a/lib/pages/settings_emotes/settings_emotes_view.dart +++ b/lib/pages/settings_emotes/settings_emotes_view.dart @@ -19,6 +19,8 @@ class EmotesSettingsView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final client = Matrix.of(context).client; final imageKeys = controller.pack!.images.keys.toList(); return Scaffold( @@ -73,7 +75,7 @@ class EmotesSettingsView extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(10)), - color: Theme.of(context).secondaryHeaderColor, + color: theme.secondaryHeaderColor, ), child: TextField( controller: controller.newImageCodeController, @@ -85,11 +87,11 @@ class EmotesSettingsView extends StatelessWidget { prefixText: ': ', suffixText: ':', prefixStyle: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), suffixStyle: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), border: InputBorder.none, @@ -117,7 +119,7 @@ class EmotesSettingsView extends StatelessWidget { onChanged: controller.setIsGloballyActive, ), if (!controller.readonly || controller.room != null) - const Divider(thickness: 1), + const Divider(), imageKeys.isEmpty ? Center( child: Padding( @@ -152,7 +154,7 @@ class EmotesSettingsView extends StatelessWidget { decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(10)), - color: Theme.of(context).secondaryHeaderColor, + color: theme.secondaryHeaderColor, ), child: Shortcuts( shortcuts: !useShortCuts @@ -188,13 +190,11 @@ class EmotesSettingsView extends StatelessWidget { prefixText: ': ', suffixText: ':', prefixStyle: TextStyle( - color: - Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), suffixStyle: TextStyle( - color: - Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), border: InputBorder.none, diff --git a/lib/pages/settings_ignore_list/settings_ignore_list.dart b/lib/pages/settings_ignore_list/settings_ignore_list.dart index d64be058b..0468d267b 100644 --- a/lib/pages/settings_ignore_list/settings_ignore_list.dart +++ b/lib/pages/settings_ignore_list/settings_ignore_list.dart @@ -22,8 +22,9 @@ class SettingsIgnoreListController extends State { @override void initState() { super.initState(); - if (widget.initialUserId != null) { - controller.text = widget.initialUserId!.replaceAll('@', ''); + final initialUserId = widget.initialUserId; + if (initialUserId != null) { + controller.text = initialUserId; } } diff --git a/lib/pages/settings_ignore_list/settings_ignore_list_view.dart b/lib/pages/settings_ignore_list/settings_ignore_list_view.dart index 785249c69..4ce3a58e1 100644 --- a/lib/pages/settings_ignore_list/settings_ignore_list_view.dart +++ b/lib/pages/settings_ignore_list/settings_ignore_list_view.dart @@ -15,6 +15,8 @@ class SettingsIgnoreListView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final client = Matrix.of(context).client; return Scaffold( appBar: AppBar( @@ -43,7 +45,7 @@ class SettingsIgnoreListView extends StatelessWidget { labelText: L10n.of(context)!.blockUsername, suffixIcon: IconButton( tooltip: L10n.of(context)!.block, - icon: const Icon(Icons.send_outlined), + icon: const Icon(Icons.add), onPressed: () => controller.ignoreUser(context), ), ), @@ -57,7 +59,7 @@ class SettingsIgnoreListView extends StatelessWidget { ), ), Divider( - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), Expanded( child: StreamBuilder( diff --git a/lib/pages/settings_notifications/settings_notifications_view.dart b/lib/pages/settings_notifications/settings_notifications_view.dart index 6c1d45cc5..0128b7593 100644 --- a/lib/pages/settings_notifications/settings_notifications_view.dart +++ b/lib/pages/settings_notifications/settings_notifications_view.dart @@ -30,6 +30,7 @@ class SettingsNotificationsView extends StatelessWidget { false, ), builder: (BuildContext context, _) { + final theme = Theme.of(context); return Column( children: [ SwitchListTile.adaptive( @@ -41,12 +42,12 @@ class SettingsNotificationsView extends StatelessWidget { ? null : (_) => controller.onToggleMuteAllNotifications(), ), - Divider(color: Theme.of(context).dividerColor), + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context)!.notifyMeFor, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -64,12 +65,12 @@ class SettingsNotificationsView extends StatelessWidget { : (bool enabled) => controller .setNotificationSetting(item, enabled), ), - Divider(color: Theme.of(context).dividerColor), + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context)!.devices, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), diff --git a/lib/pages/settings_password/settings_password_view.dart b/lib/pages/settings_password/settings_password_view.dart index 813bebd18..3e9b64f33 100644 --- a/lib/pages/settings_password/settings_password_view.dart +++ b/lib/pages/settings_password/settings_password_view.dart @@ -12,30 +12,19 @@ class SettingsPasswordView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return Scaffold( appBar: AppBar( title: Text(L10n.of(context)!.changePassword), - actions: [ - TextButton( - child: Text(L10n.of(context)!.passwordRecoverySettings), - onPressed: () => context.go('/rooms/settings/security/3pid'), - ), - ], ), body: ListTileTheme( - iconColor: Theme.of(context).colorScheme.onSurface, + iconColor: theme.colorScheme.onSurface, child: MaxWidthBody( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ - Center( - child: Icon( - Icons.key_outlined, - color: Theme.of(context).dividerColor, - size: 80, - ), - ), const SizedBox(height: 16), TextField( controller: controller.oldPasswordController, @@ -44,18 +33,22 @@ class SettingsPasswordView extends StatelessWidget { autofocus: true, readOnly: controller.loading, decoration: InputDecoration( - hintText: L10n.of(context)!.pleaseEnterYourCurrentPassword, + prefixIcon: const Icon(Icons.lock_outlined), + hintText: '********', + labelText: L10n.of(context)!.pleaseEnterYourCurrentPassword, errorText: controller.oldPasswordError, ), ), - const Divider(height: 32), + const Divider(height: 64), TextField( controller: controller.newPassword1Controller, obscureText: true, autocorrect: false, readOnly: controller.loading, decoration: InputDecoration( - hintText: L10n.of(context)!.newPassword, + prefixIcon: const Icon(Icons.lock_reset_outlined), + hintText: '********', + labelText: L10n.of(context)!.newPassword, errorText: controller.newPassword1Error, ), ), @@ -66,22 +59,28 @@ class SettingsPasswordView extends StatelessWidget { autocorrect: false, readOnly: controller.loading, decoration: InputDecoration( - hintText: L10n.of(context)!.repeatPassword, + prefixIcon: const Icon(Icons.repeat_outlined), + hintText: '********', + labelText: L10n.of(context)!.repeatPassword, errorText: controller.newPassword2Error, ), ), - const SizedBox(height: 16), + const SizedBox(height: 32), SizedBox( width: double.infinity, - child: ElevatedButton.icon( + child: ElevatedButton( onPressed: controller.loading ? null : controller.changePassword, - icon: const Icon(Icons.send_outlined), - label: controller.loading + child: controller.loading ? const LinearProgressIndicator() : Text(L10n.of(context)!.changePassword), ), ), + const SizedBox(height: 16), + TextButton( + child: Text(L10n.of(context)!.passwordRecoverySettings), + onPressed: () => context.go('/rooms/settings/security/3pid'), + ), ], ), ), diff --git a/lib/pages/settings_security/settings_security_view.dart b/lib/pages/settings_security/settings_security_view.dart index 58746bd9e..7a0f5606a 100644 --- a/lib/pages/settings_security/settings_security_view.dart +++ b/lib/pages/settings_security/settings_security_view.dart @@ -17,10 +17,12 @@ class SettingsSecurityView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return Scaffold( appBar: AppBar(title: Text(L10n.of(context)!.security)), body: ListTileTheme( - iconColor: Theme.of(context).colorScheme.onSurface, + iconColor: theme.colorScheme.onSurface, child: MaxWidthBody( child: FutureBuilder( future: Matrix.of(context) @@ -44,7 +46,7 @@ class SettingsSecurityView extends StatelessWidget { title: Text( L10n.of(context)!.privacy, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -84,15 +86,12 @@ class SettingsSecurityView extends StatelessWidget { onTap: controller.setAppLockAction, ), }, - Divider( - height: 1, - color: Theme.of(context).dividerColor, - ), + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context)!.account, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -116,13 +115,14 @@ class SettingsSecurityView extends StatelessWidget { ), ListTile( iconColor: Colors.orange, - leading: const Icon(Icons.tap_and_play), + leading: const Icon(Icons.delete_sweep_outlined), title: Text( L10n.of(context)!.dehydrate, style: const TextStyle(color: Colors.orange), ), onTap: controller.dehydrateAction, ), + Divider(color: theme.dividerColor), ListTile( iconColor: Colors.red, leading: const Icon(Icons.delete_outlined), diff --git a/lib/pages/settings_style/settings_style_view.dart b/lib/pages/settings_style/settings_style_view.dart index 86f48fe87..fd0a4c4f9 100644 --- a/lib/pages/settings_style/settings_style_view.dart +++ b/lib/pages/settings_style/settings_style_view.dart @@ -20,6 +20,8 @@ class SettingsStyleView extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + const colorPickerSize = 32.0; final client = Matrix.of(context).client; return Scaffold( @@ -27,7 +29,7 @@ class SettingsStyleView extends StatelessWidget { leading: const Center(child: BackButton()), title: Text(L10n.of(context)!.changeTheme), ), - backgroundColor: Theme.of(context).colorScheme.surface, + backgroundColor: theme.colorScheme.surface, body: MaxWidthBody( child: Column( children: [ @@ -35,7 +37,7 @@ class SettingsStyleView extends StatelessWidget { title: Text( L10n.of(context)!.setColorTheme, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -88,18 +90,16 @@ class SettingsStyleView extends StatelessWidget { child: Icon( Icons.check, size: 16, - color: Theme.of(context) - .colorScheme - .onSurface, + color: theme + .colorScheme.onSurface, ), ), Text( L10n.of(context)!.systemTheme, textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface, + color: theme + .colorScheme.onSurface, ), ), ], @@ -136,14 +136,13 @@ class SettingsStyleView extends StatelessWidget { ), const SizedBox(height: 8), Divider( - height: 1, - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), ListTile( title: Text( L10n.of(context)!.setTheme, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -167,14 +166,13 @@ class SettingsStyleView extends StatelessWidget { onChanged: controller.switchTheme, ), Divider( - height: 1, - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), ListTile( title: Text( L10n.of(context)!.overview, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -192,14 +190,13 @@ class SettingsStyleView extends StatelessWidget { defaultValue: AppConfig.separateChatTypes, ), Divider( - height: 1, - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), ListTile( title: Text( L10n.of(context)!.messagesStyle, style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, ), ), @@ -249,7 +246,7 @@ class SettingsStyleView extends StatelessWidget { bottom: 12, ), child: Material( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, borderRadius: BorderRadius.circular( AppConfig.borderRadius, ), @@ -261,8 +258,7 @@ class SettingsStyleView extends StatelessWidget { child: Text( 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor', style: TextStyle( - color: - Theme.of(context).colorScheme.onPrimary, + color: theme.colorScheme.onPrimary, fontSize: AppConfig.messageFontSize * AppConfig.fontSizeFactor, ), @@ -280,7 +276,7 @@ class SettingsStyleView extends StatelessWidget { ? null : IconButton( icon: const Icon(Icons.delete_outlined), - color: Theme.of(context).colorScheme.error, + color: theme.colorScheme.error, onPressed: controller.deleteChatWallpaper, ), onTap: controller.setWallpaper, diff --git a/lib/pages/user_bottom_sheet/user_bottom_sheet.dart b/lib/pages/user_bottom_sheet/user_bottom_sheet.dart index 7446aebc7..7a19043e8 100644 --- a/lib/pages/user_bottom_sheet/user_bottom_sheet.dart +++ b/lib/pages/user_bottom_sheet/user_bottom_sheet.dart @@ -236,6 +236,45 @@ class UserBottomSheetController extends State { } } + bool isSending = false; + + Object? sendError; + + final TextEditingController sendController = TextEditingController(); + + void sendAction([_]) async { + final userId = widget.user?.id ?? widget.profile?.userId; + final client = Matrix.of(widget.outerContext).client; + if (userId == null) throw ('user or profile must not be null!'); + + final input = sendController.text.trim(); + if (input.isEmpty) return; + + setState(() { + isSending = true; + sendError = null; + }); + try { + final roomId = await client.startDirectChat(userId); + if (!mounted) return; + final room = client.getRoomById(roomId); + if (room == null) { + throw ('DM Room found or created but room not found in client'); + } + await room.sendTextEvent(input); + setState(() { + isSending = false; + sendController.clear(); + }); + } catch (e, s) { + Logs().d('Unable to send message', e, s); + setState(() { + isSending = false; + sendError = e; + }); + } + } + void knockAccept() async { final user = widget.user!; final result = await showFutureLoadingDialog( diff --git a/lib/pages/user_bottom_sheet/user_bottom_sheet_view.dart b/lib/pages/user_bottom_sheet/user_bottom_sheet_view.dart index ef79c0e31..237efd1c8 100644 --- a/lib/pages/user_bottom_sheet/user_bottom_sheet_view.dart +++ b/lib/pages/user_bottom_sheet/user_bottom_sheet_view.dart @@ -2,6 +2,7 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/utils/bot_name.dart'; import 'package:fluffychat/utils/date_time_extension.dart'; import 'package:fluffychat/utils/fluffy_share.dart'; +import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/url_launcher.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/presence_builder.dart'; @@ -29,6 +30,7 @@ class UserBottomSheetView extends StatelessWidget { final client = Matrix.of(controller.widget.outerContext).client; final profileSearchError = controller.widget.profileSearchError; + final dmRoomId = client.getDirectChatFromUserId(userId); return SafeArea( child: Scaffold( appBar: AppBar( @@ -36,78 +38,20 @@ class UserBottomSheetView extends StatelessWidget { onPressed: Navigator.of(context, rootNavigator: false).pop, ), centerTitle: false, - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(displayname), - PresenceBuilder( - userId: userId, - client: client, - builder: (context, presence) { - if (presence == null || - (presence.presence == PresenceType.offline && - presence.lastActiveTimestamp == null)) { - return const SizedBox.shrink(); - } - - final dotColor = presence.presence.isOnline - ? Colors.green - : presence.presence.isUnavailable - ? Colors.orange - : Colors.grey; - - final lastActiveTimestamp = presence.lastActiveTimestamp; - - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 8, - height: 8, - margin: const EdgeInsets.only(right: 8), - decoration: BoxDecoration( - color: dotColor, - borderRadius: BorderRadius.circular(16), - ), - ), - if (presence.currentlyActive == true) - Text( - L10n.of(context)!.currentlyActive, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodySmall, - ) - else if (lastActiveTimestamp != null) - Text( - L10n.of(context)!.lastActiveAgo( - lastActiveTimestamp.localizedTimeShort(context), - ), - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodySmall, - ), - ], - ); - }, - ), - ], - ), - actions: [ - if (userId != client.userID && - !client.ignoredUsers.contains(userId) - // #Pangea - && - userId != BotName.byEnvironment - // Pangea# - ) - Padding( - padding: const EdgeInsets.only(right: 8.0), - child: IconButton( - icon: const Icon(Icons.block_outlined), - tooltip: L10n.of(context)!.block, - onPressed: () => controller - .participantAction(UserBottomSheetAction.ignore), - ), - ), - ], + title: Text(displayname), + actions: dmRoomId == null + ? null + : [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: FloatingActionButton.small( + elevation: 0, + onPressed: () => controller + .participantAction(UserBottomSheetAction.message), + child: const Icon(Icons.chat_outlined), + ), + ), + ], ), body: StreamBuilder( stream: user?.room.client.onSync.stream.where( @@ -118,6 +62,7 @@ class UserBottomSheetView extends StatelessWidget { false, ), builder: (context, snapshot) { + final theme = Theme.of(context); return ListView( children: [ if (user?.membership == Membership.knock) @@ -126,7 +71,7 @@ class UserBottomSheetView extends StatelessWidget { child: Material( color: // ignore: deprecated_member_use - Theme.of(context).colorScheme.surfaceVariant, + theme.colorScheme.surfaceVariant, borderRadius: BorderRadius.circular(AppConfig.borderRadius), child: ListTile( @@ -142,10 +87,8 @@ class UserBottomSheetView extends StatelessWidget { children: [ TextButton.icon( style: TextButton.styleFrom( - backgroundColor: - Theme.of(context).colorScheme.surface, - foregroundColor: - Theme.of(context).colorScheme.primary, + backgroundColor: theme.colorScheme.surface, + foregroundColor: theme.colorScheme.primary, ), onPressed: controller.knockAccept, icon: const Icon(Icons.check_outlined), @@ -154,12 +97,10 @@ class UserBottomSheetView extends StatelessWidget { const SizedBox(width: 12), TextButton.icon( style: TextButton.styleFrom( - backgroundColor: Theme.of(context) - .colorScheme - .errorContainer, - foregroundColor: Theme.of(context) - .colorScheme - .onErrorContainer, + backgroundColor: + theme.colorScheme.errorContainer, + foregroundColor: + theme.colorScheme.onErrorContainer, ), onPressed: controller.knockDecline, icon: const Icon(Icons.cancel_outlined), @@ -174,25 +115,12 @@ class UserBottomSheetView extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.all(16.0), - child: Material( - elevation: Theme.of(context) - .appBarTheme - .scrolledUnderElevation ?? - 4, - shadowColor: Theme.of(context).appBarTheme.shadowColor, - shape: RoundedRectangleBorder( - side: BorderSide( - color: Theme.of(context).dividerColor, - ), - borderRadius: BorderRadius.circular( - Avatar.defaultSize * 2.5, - ), - ), - child: Avatar( - mxContent: avatarUrl, - name: displayname, - size: Avatar.defaultSize * 2.5, - ), + child: Avatar( + client: + Matrix.of(controller.widget.outerContext).client, + mxContent: avatarUrl, + name: displayname, + size: Avatar.defaultSize * 2.5, ), ), Expanded( @@ -200,26 +128,6 @@ class UserBottomSheetView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - TextButton.icon( - onPressed: () => FluffyShare.share( - 'https://matrix.to/#/$userId', - context, - ), - icon: Icon( - Icons.adaptive.share_outlined, - size: 16, - ), - style: TextButton.styleFrom( - foregroundColor: - Theme.of(context).colorScheme.onSurface, - ), - label: Text( - displayname, - maxLines: 1, - overflow: TextOverflow.ellipsis, - // style: const TextStyle(fontSize: 18), - ), - ), TextButton.icon( onPressed: () => FluffyShare.share( userId, @@ -231,38 +139,70 @@ class UserBottomSheetView extends StatelessWidget { size: 14, ), style: TextButton.styleFrom( - foregroundColor: - Theme.of(context).colorScheme.secondary, + foregroundColor: theme.colorScheme.onSurface, ), label: Text( userId, maxLines: 1, overflow: TextOverflow.ellipsis, - // style: const TextStyle(fontSize: 12), ), ), + PresenceBuilder( + userId: userId, + client: client, + builder: (context, presence) { + if (presence == null || + (presence.presence == PresenceType.offline && + presence.lastActiveTimestamp == null)) { + return const SizedBox.shrink(); + } + + final dotColor = presence.presence.isOnline + ? Colors.green + : presence.presence.isUnavailable + ? Colors.orange + : Colors.grey; + + final lastActiveTimestamp = + presence.lastActiveTimestamp; + + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(width: 16), + Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: dotColor, + borderRadius: BorderRadius.circular(16), + ), + ), + const SizedBox(width: 12), + if (presence.currentlyActive == true) + Text( + L10n.of(context)!.currentlyActive, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodySmall, + ) + else if (lastActiveTimestamp != null) + Text( + L10n.of(context)!.lastActiveAgo( + lastActiveTimestamp + .localizedTimeShort(context), + ), + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodySmall, + ), + ], + ); + }, + ), ], ), ), ], ), - if (userId != client.userID) - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: ElevatedButton.icon( - onPressed: () => controller - .participantAction(UserBottomSheetAction.message), - icon: const Icon(Icons.forum_outlined), - label: Text( - controller.widget.user == null - ? L10n.of(context)!.startConversation - : L10n.of(context)!.sendAMessage, - ), - ), - ), PresenceBuilder( userId: userId, client: client, @@ -286,6 +226,49 @@ class UserBottomSheetView extends StatelessWidget { ); }, ), + if (userId != client.userID) + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: dmRoomId == null + ? ElevatedButton.icon( + onPressed: () => controller.participantAction( + UserBottomSheetAction.message, + ), + icon: const Icon(Icons.chat_outlined), + label: Text(L10n.of(context)!.startConversation), + ) + : TextField( + controller: controller.sendController, + readOnly: controller.isSending, + onSubmitted: controller.sendAction, + minLines: 1, + maxLines: 1, + textInputAction: TextInputAction.send, + decoration: InputDecoration( + errorText: controller.sendError + ?.toLocalizedString(context), + hintText: L10n.of(context)!.sendMessages, + suffix: controller.isSending + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator.adaptive( + strokeWidth: 2, + ), + ) + : null, + suffixIcon: controller.isSending + ? null + : IconButton( + icon: const Icon(Icons.send_outlined), + onPressed: controller.sendAction, + ), + ), + ), + ), if (controller.widget.onMention != null) ListTile( leading: const Icon(Icons.alternate_email_outlined), @@ -294,7 +277,7 @@ class UserBottomSheetView extends StatelessWidget { .participantAction(UserBottomSheetAction.mention), ), if (user != null) ...[ - Divider(color: Theme.of(context).dividerColor), + Divider(color: theme.dividerColor), ListTile( title: Text( '${L10n.of(context)!.userRole} (${user.powerLevel})', @@ -303,7 +286,7 @@ class UserBottomSheetView extends StatelessWidget { trailing: Material( borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, child: DropdownButton( onChanged: user.canChangeUserPowerLevel || // Workaround until https://github.com/famedly/matrix-dart-sdk/pull/1765 @@ -339,12 +322,12 @@ class UserBottomSheetView extends StatelessWidget { ), ), ), - Divider(color: Theme.of(context).dividerColor), ], + Divider(color: theme.dividerColor), if (user != null && user.canKick) ListTile( - textColor: Theme.of(context).colorScheme.error, - iconColor: Theme.of(context).colorScheme.error, + textColor: theme.colorScheme.error, + iconColor: theme.colorScheme.error, title: Text(L10n.of(context)!.kickFromChat), leading: const Icon(Icons.exit_to_app_outlined), onTap: () => controller @@ -354,8 +337,8 @@ class UserBottomSheetView extends StatelessWidget { user.canBan && user.membership != Membership.ban) ListTile( - textColor: Theme.of(context).colorScheme.onErrorContainer, - iconColor: Theme.of(context).colorScheme.onErrorContainer, + textColor: theme.colorScheme.onErrorContainer, + iconColor: theme.colorScheme.onErrorContainer, title: Text(L10n.of(context)!.banFromChat), leading: const Icon(Icons.warning_sharp), onTap: () => @@ -373,10 +356,10 @@ class UserBottomSheetView extends StatelessWidget { // #Pangea // if (user != null && user.id != client.userID) // ListTile( - // textColor: Theme.of(context).colorScheme.onErrorContainer, - // iconColor: Theme.of(context).colorScheme.onErrorContainer, + // textColor: theme.colorScheme.onErrorContainer, + // iconColor: theme.colorScheme.onErrorContainer, // title: Text(L10n.of(context)!.reportUser), - // leading: const Icon(Icons.report_outlined), + // leading: const Icon(Icons.gavel_outlined), // onTap: () => controller // .participantAction(UserBottomSheetAction.report), // ), @@ -392,6 +375,21 @@ class UserBottomSheetView extends StatelessWidget { style: const TextStyle(color: Colors.orange), ), ), + if (userId != client.userID && + !client.ignoredUsers.contains(userId) + // #Pangea + && + userId != BotName.byEnvironment + // Pangea# + ) + ListTile( + textColor: theme.colorScheme.onErrorContainer, + iconColor: theme.colorScheme.onErrorContainer, + leading: const Icon(Icons.block_outlined), + title: Text(L10n.of(context)!.block), + onTap: () => controller + .participantAction(UserBottomSheetAction.ignore), + ), ], ); }, diff --git a/lib/pangea/choreographer/controllers/it_controller.dart b/lib/pangea/choreographer/controllers/it_controller.dart index 74bce2f92..c3ce49575 100644 --- a/lib/pangea/choreographer/controllers/it_controller.dart +++ b/lib/pangea/choreographer/controllers/it_controller.dart @@ -3,7 +3,9 @@ import 'dart:developer'; import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart'; import 'package:fluffychat/pangea/constants/choreo_constants.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/enum/instructions_enum.dart'; +import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -50,7 +52,6 @@ class ITController { payLoadIds = []; choreographer.altTranslator.clear(); - choreographer.errorService.resetError(); choreographer.choreoMode = ChoreoMode.igc; choreographer.setState(); } @@ -303,6 +304,20 @@ class ITController { showChoiceFeedback = true; + // Get a list of the choices that the user did not click + final List? ignoredTokens = currentITStep?.continuances + .where((e) => !e.wasClicked) + .map((e) => e.tokens) + .expand((e) => e) + .toList(); + + // Save those choices' tokens to local construct analytics as ignored tokens + choreographer.pangeaController.myAnalytics.addDraftUses( + ignoredTokens ?? [], + choreographer.roomId, + ConstructUseTypeEnum.ignIt, + ); + Future.delayed( const Duration( milliseconds: ChoreoConstants.millisecondsToDisplayFeedback, diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index f7d928f0c..78e199ca1 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -7,9 +7,11 @@ import 'package:fluffychat/pangea/choreographer/widgets/it_bar_buttons.dart'; import 'package:fluffychat/pangea/choreographer/widgets/it_feedback_card.dart'; import 'package:fluffychat/pangea/choreographer/widgets/translation_finished_flow.dart'; import 'package:fluffychat/pangea/constants/choreo_constants.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/enum/instructions_enum.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/inline_tooltip.dart'; +import 'package:fluffychat/pangea/widgets/animations/gain_points.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -80,7 +82,12 @@ class ITBarState extends State { width: double.infinity, padding: const EdgeInsets.fromLTRB(0, 3, 3, 3), child: Stack( + alignment: Alignment.topCenter, children: [ + const Positioned( + top: 60, + child: PointsGainedAnimation(), + ), SingleChildScrollView( child: Column( children: [ @@ -333,6 +340,35 @@ class ITChoices extends StatelessWidget { ); } + void selectContinuance(int index, BuildContext context) { + final Continuance continuance = + controller.currentITStep!.continuances[index]; + if (continuance.level == 1 || continuance.wasClicked) { + Future.delayed( + const Duration(milliseconds: 500), + () => controller.selectTranslation(index), + ); + } else { + showCard( + context, + index, + continuance.level == 2 ? ChoreoConstants.yellow : ChoreoConstants.red, + continuance.feedbackText(context), + ); + } + if (!continuance.wasClicked) { + controller.choreographer.pangeaController.myAnalytics.addDraftUses( + continuance.tokens, + controller.choreographer.roomId, + continuance.level > 1 + ? ConstructUseTypeEnum.incIt + : ConstructUseTypeEnum.corIt, + ); + } + controller.currentITStep!.continuances[index].wasClicked = true; + controller.choreographer.setState(); + } + @override Widget build(BuildContext context) { try { @@ -357,31 +393,8 @@ class ITChoices extends StatelessWidget { return Choice(text: "error", color: Colors.red); } }).toList(), - onPressed: (int index) { - final Continuance continuance = - controller.currentITStep!.continuances[index]; - debugPrint("is gold? ${continuance.gold}"); - if (continuance.level == 1 || continuance.wasClicked) { - Future.delayed( - const Duration(milliseconds: 500), - () => controller.selectTranslation(index), - ); - } else { - showCard( - context, - index, - continuance.level == 2 - ? ChoreoConstants.yellow - : ChoreoConstants.red, - continuance.feedbackText(context), - ); - } - controller.currentITStep!.continuances[index].wasClicked = true; - controller.choreographer.setState(); - }, - onLongPress: (int index) { - showCard(context, index); - }, + onPressed: (int index) => selectContinuance(index, context), + onLongPress: (int index) => showCard(context, index), uniqueKeyForLayerLink: (int index) => "itChoices$index", selectedChoiceIndex: null, ); diff --git a/lib/pangea/choreographer/widgets/start_igc_button.dart b/lib/pangea/choreographer/widgets/start_igc_button.dart index d1d45bb6b..39d35a5a9 100644 --- a/lib/pangea/choreographer/widgets/start_igc_button.dart +++ b/lib/pangea/choreographer/widgets/start_igc_button.dart @@ -41,16 +41,21 @@ class StartIGCButtonState extends State super.initState(); } + @override + void dispose() { + _controller?.dispose(); + choreoListener?.cancel(); + super.dispose(); + } + void updateSpinnerState(_) { if (prevState != AssistanceState.fetching && assistanceState == AssistanceState.fetching) { _controller?.repeat(); } else if (prevState == AssistanceState.fetching && assistanceState != AssistanceState.fetching) { - _controller?.stop(); - _controller?.reverse(); + _controller?.reset(); } - if (mounted) { setState(() => prevState = assistanceState); } diff --git a/lib/pangea/constants/analytics_constants.dart b/lib/pangea/constants/analytics_constants.dart new file mode 100644 index 000000000..fb7c356f8 --- /dev/null +++ b/lib/pangea/constants/analytics_constants.dart @@ -0,0 +1,5 @@ +class AnalyticsConstants { + static const int xpPerLevel = 2000; + static const int vocabUseMaxXP = 30; + static const int morphUseMaxXP = 500; +} diff --git a/lib/pangea/controllers/get_analytics_controller.dart b/lib/pangea/controllers/get_analytics_controller.dart new file mode 100644 index 000000000..e23b30d1e --- /dev/null +++ b/lib/pangea/controllers/get_analytics_controller.dart @@ -0,0 +1,323 @@ +import 'dart:async'; + +import 'package:fluffychat/pangea/constants/analytics_constants.dart'; +import 'package:fluffychat/pangea/constants/class_default_values.dart'; +import 'package:fluffychat/pangea/constants/local.key.dart'; +import 'package:fluffychat/pangea/constants/match_rule_ids.dart'; +import 'package:fluffychat/pangea/controllers/my_analytics_controller.dart'; +import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; +import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; +import 'package:fluffychat/pangea/models/analytics/construct_list_model.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_event.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; +import 'package:matrix/src/utils/cached_stream_controller.dart'; +import 'package:sentry_flutter/sentry_flutter.dart'; + +/// A minimized version of AnalyticsController that get the logged in user's analytics +class GetAnalyticsController { + late PangeaController _pangeaController; + final List _cache = []; + StreamSubscription? _analyticsUpdateSubscription; + CachedStreamController> analyticsStream = + CachedStreamController>(); + + /// The previous XP points of the user, before the last update. + /// Used for animating analytics updates. + int? prevXP; + + GetAnalyticsController(PangeaController pangeaController) { + _pangeaController = pangeaController; + } + + String? get l2Code => _pangeaController.languageController.userL2?.langCode; + Client get client => _pangeaController.matrixState.client; + + int get currentXP => calcXP(allConstructUses); + int get localXP => calcXP(locallyCachedConstructs); + int get serverXP => currentXP - localXP; + + /// Get the current level based on the number of xp points + int get level => currentXP ~/ AnalyticsConstants.xpPerLevel; + + void initialize() { + _analyticsUpdateSubscription ??= _pangeaController + .myAnalytics.analyticsUpdateStream.stream + .listen(onAnalyticsUpdate); + + _pangeaController.myAnalytics.lastUpdatedCompleter.future.then((_) { + getConstructs().then((_) => updateAnalyticsStream()); + }); + } + + /// Clear all cached analytics data. + void dispose() { + _analyticsUpdateSubscription?.cancel(); + _analyticsUpdateSubscription = null; + _cache.clear(); + analyticsStream.add([]); + prevXP = null; + } + + Future onAnalyticsUpdate(AnalyticsUpdateType type) async { + if (type == AnalyticsUpdateType.server) { + await getConstructs(forceUpdate: true); + } + updateAnalyticsStream(); + } + + void updateAnalyticsStream() { + // if there are no construct uses, or if the last update in this + // stream has the same length as this update, don't update the stream + if (allConstructUses.isEmpty || + allConstructUses.length == analyticsStream.value?.length) { + return; + } + + // set the previous XP to the currentXP + if (analyticsStream.value != null && analyticsStream.value!.isNotEmpty) { + prevXP = calcXP(analyticsStream.value!); + } + + // finally, add to the stream + analyticsStream.add(allConstructUses); + } + + /// Calculates the user's xpPoints for their current L2, + /// based on matrix analytics event and locally cached data. + /// Has to be async because cached matrix events may be out of date, + /// and updating those is async. + int calcXP(List constructs) { + final words = ConstructListModel( + uses: constructs, + type: ConstructTypeEnum.vocab, + ); + final errors = ConstructListModel( + uses: constructs, + type: ConstructTypeEnum.grammar, + ); + return words.points + errors.points; + } + + List get allConstructUses { + final List storedUses = getConstructsLocal() ?? []; + final List localUses = locallyCachedConstructs; + + final List allConstructs = [ + ...storedUses, + ...localUses, + ]; + + return allConstructs; + } + + /// A local cache of eventIds and construct uses for messages sent since the last update. + /// It's a map of eventIDs to a list of OneConstructUses. Not just a list of OneConstructUses + /// because, with practice activity constructs, we might need to add to the list for a given + /// eventID. + Map> get messagesSinceUpdate { + try { + final dynamic locallySaved = _pangeaController.pStoreService.read( + PLocalKey.messagesSinceUpdate, + ); + if (locallySaved == null) return {}; + try { + // try to get the local cache of messages and format them as OneConstructUses + final Map> cache = + Map>.from(locallySaved); + final Map> formattedCache = {}; + for (final entry in cache.entries) { + formattedCache[entry.key] = + entry.value.map((e) => OneConstructUse.fromJson(e)).toList(); + } + return formattedCache; + } catch (err) { + // if something goes wrong while trying to format the local data, clear it + _pangeaController.myAnalytics.clearMessagesSinceUpdate(); + return {}; + } + } catch (exception, stackTrace) { + ErrorHandler.logError( + e: PangeaWarningError( + "Failed to get messages since update: $exception", + ), + s: stackTrace, + m: 'Failed to retrieve messages since update', + ); + return {}; + } + } + + /// A flat list of all locally cached construct uses + List get locallyCachedConstructs => + messagesSinceUpdate.values.expand((e) => e).toList(); + + /// A flat list of all locally cached construct uses that are not drafts + List get locallyCachedSentConstructs => + messagesSinceUpdate.entries + .where((entry) => !entry.key.startsWith('draft')) + .expand((e) => e.value) + .toList(); + + /// Get a list of all constructs used by the logged in user in their current L2 + Future> getConstructs({ + bool forceUpdate = false, + ConstructTypeEnum? constructType, + }) async { + // if the user isn't logged in, return an empty list + if (client.userID == null) return []; + await client.roomsLoading; + + // don't try to get constructs until last updated time has been loaded + await _pangeaController.myAnalytics.lastUpdatedCompleter.future; + + // if forcing a refreshing, clear the cache + if (forceUpdate) _cache.clear(); + + final List? local = getConstructsLocal( + constructType: constructType, + ); + + if (local != null) { + debugPrint("returning local constructs"); + return local; + } + debugPrint("fetching new constructs"); + + // if there is no cached data (or if force updating), + // get all the construct events for the user from analytics room + // and convert their content into a list of construct uses + final List constructEvents = + await allMyConstructs(); + + final List unfilteredUses = []; + for (final event in constructEvents) { + unfilteredUses.addAll(event.content.uses); + } + + // filter out any constructs that are not relevant to the user + final List filteredUses = await filterConstructs( + unfilteredConstructs: unfilteredUses, + ); + + // if there isn't already a valid, local cache, cache the filtered uses + if (local == null) { + cacheConstructs( + constructType: constructType, + uses: filteredUses, + ); + } + + return filteredUses; + } + + /// Get the last time the user updated their analytics for their current l2 + Future myAnalyticsLastUpdated() async { + // this function gets called soon after login, so first + // make sure that the user's l2 is loaded, if the user has set their l2 + if (client.userID != null && l2Code == null) { + await _pangeaController.matrixState.client.waitForAccountData(); + if (l2Code == null) return null; + } + final Room? analyticsRoom = client.analyticsRoomLocal(l2Code!); + if (analyticsRoom == null) return null; + final DateTime? lastUpdated = await analyticsRoom.analyticsLastUpdated( + client.userID!, + ); + return lastUpdated; + } + + /// Get all the construct analytics events for the logged in user + Future> allMyConstructs() async { + if (l2Code == null) return []; + final Room? analyticsRoom = client.analyticsRoomLocal(l2Code!); + if (analyticsRoom == null) return []; + return await analyticsRoom.getAnalyticsEvents(userId: client.userID!) ?? []; + } + + /// Filter out constructs that are not relevant to the user, specifically those from + /// rooms in which the user is a teacher and those that are interative translation span constructs + Future> filterConstructs({ + required List unfilteredConstructs, + }) async { + return unfilteredConstructs + .where( + (use) => + use.lemma != "Try interactive translation" && + use.lemma != "itStart" || + use.lemma != MatchRuleIds.interactiveTranslation, + ) + .toList(); + } + + /// Get the cached construct uses for the current user, if it exists + List? getConstructsLocal({ + ConstructTypeEnum? constructType, + }) { + final index = _cache.indexWhere( + (e) => e.type == constructType && e.langCode == l2Code, + ); + + if (index > -1) { + final DateTime? lastUpdated = _pangeaController.myAnalytics.lastUpdated; + if (_cache[index].needsUpdate(lastUpdated)) { + _cache.removeAt(index); + return null; + } + return _cache[index].uses; + } + + return null; + } + + /// Cache the construct uses for the current user + void cacheConstructs({ + required List uses, + ConstructTypeEnum? constructType, + }) { + if (l2Code == null) return; + final entry = AnalyticsCacheEntry( + type: constructType, + uses: List.from(uses), + langCode: l2Code!, + ); + _cache.add(entry); + } +} + +class AnalyticsCacheEntry { + final String langCode; + final ConstructTypeEnum? type; + final List uses; + late final DateTime _createdAt; + + AnalyticsCacheEntry({ + required this.langCode, + required this.type, + required this.uses, + }) { + _createdAt = DateTime.now(); + } + + bool get isExpired => + DateTime.now().difference(_createdAt).inMinutes > + ClassDefaultValues.minutesDelayToMakeNewChartAnalytics; + + bool needsUpdate(DateTime? lastEventUpdated) { + // cache entry is invalid if it's older than the last event update + // if lastEventUpdated is null, that would indicate that no events + // of this type have been sent to the room. In this case, there + // shouldn't be any cached data. + if (lastEventUpdated == null) { + Sentry.addBreadcrumb( + Breadcrumb(message: "lastEventUpdated is null in needsUpdate"), + ); + return false; + } + return _createdAt.isBefore(lastEventUpdated); + } +} diff --git a/lib/pangea/controllers/message_analytics_controller.dart b/lib/pangea/controllers/message_analytics_controller.dart index 32aaf66fc..29cbef9ea 100644 --- a/lib/pangea/controllers/message_analytics_controller.dart +++ b/lib/pangea/controllers/message_analytics_controller.dart @@ -1,16 +1,9 @@ import 'dart:async'; -import 'dart:developer'; -import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/constants/match_rule_ids.dart'; -import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; -import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; import 'package:fluffychat/pangea/enum/time_span.dart'; -import 'package:fluffychat/pangea/models/analytics/analytics_event.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_event.dart'; -import 'package:fluffychat/pangea/models/analytics/summary_analytics_event.dart'; -import 'package:fluffychat/pangea/models/language_model.dart'; import 'package:fluffychat/pangea/pages/analytics/base_analytics.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; @@ -20,89 +13,87 @@ import 'package:sentry_flutter/sentry_flutter.dart'; import '../constants/class_default_values.dart'; import '../extensions/client_extension/client_extension.dart'; import '../extensions/pangea_room_extension/pangea_room_extension.dart'; -import '../models/analytics/chart_analytics_model.dart'; import 'base_controller.dart'; import 'pangea_controller.dart'; // controls the fetching of analytics data class AnalyticsController extends BaseController { late PangeaController _pangeaController; - - final List _cachedAnalyticsModels = []; final List _cachedConstructs = []; AnalyticsController(PangeaController pangeaController) : super() { _pangeaController = pangeaController; } - ///////// TIME SPANS ////////// - String get _analyticsTimeSpanKey => "ANALYTICS_TIME_SPAN_KEY"; + String get langCode => + _pangeaController.languageController.userL2?.langCode ?? + _pangeaController.pLanguageStore.targetOptions.first.langCode; - TimeSpan get currentAnalyticsTimeSpan { - try { - final String? str = _pangeaController.pStoreService.read( - _analyticsTimeSpanKey, - ); - return str != null - ? TimeSpan.values.firstWhere((e) { - final spanString = e.toString(); - return spanString == str; - }) - : ClassDefaultValues.defaultTimeSpan; - } catch (err) { - debugger(when: kDebugMode); - return ClassDefaultValues.defaultTimeSpan; - } - } + // String get _analyticsTimeSpanKey => "ANALYTICS_TIME_SPAN_KEY"; - Future setCurrentAnalyticsTimeSpan(TimeSpan timeSpan) async { - await _pangeaController.pStoreService.save( - _analyticsTimeSpanKey, - timeSpan.toString(), - ); - setState(); - } + // TimeSpan get currentAnalyticsTimeSpan { + // try { + // final String? str = _pangeaController.pStoreService.read( + // _analyticsTimeSpanKey, + // ); + // return str != null + // ? TimeSpan.values.firstWhere((e) { + // final spanString = e.toString(); + // return spanString == str; + // }) + // : ClassDefaultValues.defaultTimeSpan; + // } catch (err) { + // debugger(when: kDebugMode); + // return ClassDefaultValues.defaultTimeSpan; + // } + // } - ///////// SPACE ANALYTICS LANGUAGES ////////// - String get _analyticsSpaceLangKey => "ANALYTICS_SPACE_LANG_KEY"; + // Future setCurrentAnalyticsTimeSpan(TimeSpan timeSpan) async { + // await _pangeaController.pStoreService.save( + // _analyticsTimeSpanKey, + // timeSpan.toString(), + // ); + // setState(); + // } - LanguageModel get currentAnalyticsLang { - try { - final String? str = _pangeaController.pStoreService.read( - _analyticsSpaceLangKey, - ); - return str != null - ? PangeaLanguage.byLangCode(str) - : _pangeaController.languageController.userL2 ?? - _pangeaController.pLanguageStore.targetOptions.first; - } catch (err) { - debugger(when: kDebugMode); - return _pangeaController.pLanguageStore.targetOptions.first; - } - } + // String get _analyticsSpaceLangKey => "ANALYTICS_SPACE_LANG_KEY"; - Future setCurrentAnalyticsLang(LanguageModel lang) async { - await _pangeaController.pStoreService.save( - _analyticsSpaceLangKey, - lang.langCode, - ); - setState(); - } + // LanguageModel get currentAnalyticsLang { + // try { + // final String? str = _pangeaController.pStoreService.read( + // _analyticsSpaceLangKey, + // ); + // return str != null + // ? PangeaLanguage.byLangCode(str) + // : _pangeaController.languageController.userL2 ?? + // _pangeaController.pLanguageStore.targetOptions.first; + // } catch (err) { + // debugger(when: kDebugMode); + // return _pangeaController.pLanguageStore.targetOptions.first; + // } + // } - /// given an analytics event type and the current analytics language, - /// get the last time the user updated their analytics - Future myAnalyticsLastUpdated(String type) async { - final List analyticsRooms = _pangeaController - .matrixState.client.allMyAnalyticsRooms - .where((room) => room.isAnalyticsRoom) - .toList(); + // Future setCurrentAnalyticsLang(LanguageModel lang) async { + // await _pangeaController.pStoreService.save( + // _analyticsSpaceLangKey, + // lang.langCode, + // ); + // setState(); + // } + + /// Get the last time the user updated their analytics. + /// Tries to get the last time the user updated analytics for their current L2. + /// If there isn't yet an analytics room reacted for their L2, checks if the + /// user has any other analytics rooms and returns the most recent update time. + Future myAnalyticsLastUpdated() async { + final List analyticsRooms = + _pangeaController.matrixState.client.allMyAnalyticsRooms; final Map langCodeLastUpdates = {}; for (final Room analyticsRoom in analyticsRooms) { final String? roomLang = analyticsRoom.madeForLang; if (roomLang == null) continue; final DateTime? lastUpdated = await analyticsRoom.analyticsLastUpdated( - type, _pangeaController.matrixState.client.userID!, ); if (lastUpdated != null) { @@ -121,25 +112,20 @@ class AnalyticsController extends BaseController { ); } + /// check if any students have recently updated their analytics + /// if any have, then the cache needs to be updated Future spaceAnalyticsLastUpdated( - String type, Room space, ) async { - // check if any students have recently updated their analytics - // if any have, then the cache needs to be updated - // TODO - figure out how to do this on a per-student basis await space.requestParticipants(); final List> lastUpdatedFutures = []; for (final student in space.students) { final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(currentAnalyticsLang.langCode, student.id); + .analyticsRoomLocal(langCode, student.id); if (analyticsRoom == null) continue; lastUpdatedFutures.add( - analyticsRoom.analyticsLastUpdated( - type, - student.id, - ), + analyticsRoom.analyticsLastUpdated(student.id), ); } @@ -155,385 +141,21 @@ class AnalyticsController extends BaseController { return null; } - // Map of space ids to the last fetched hierarchy. Used when filtering - // private chat analytics to determine which children are already visible - // in the chat list - final Map> _lastFetchedHierarchies = {}; - - void setLatestHierarchy(String spaceId, GetSpaceHierarchyResponse resp) { - final List roomIds = resp.rooms.map((room) => room.roomId).toList(); - _lastFetchedHierarchies[spaceId] = roomIds; - } - - Future> getLatestSpaceHierarchy(String spaceId) async { - if (!_lastFetchedHierarchies.containsKey(spaceId)) { - final resp = - await _pangeaController.matrixState.client.getSpaceHierarchy(spaceId); - setLatestHierarchy(spaceId, resp); - } - return _lastFetchedHierarchies[spaceId] ?? []; - } - - //////////////////////////// MESSAGE SUMMARY ANALYTICS //////////////////////////// - - /// get all the summary analytics events for the current user - /// in the current language's analytics room - Future> mySummaryAnalytics() async { - final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(currentAnalyticsLang.langCode); - if (analyticsRoom == null) return []; - - final List? roomEvents = - await analyticsRoom.getAnalyticsEvents( - type: PangeaEventTypes.summaryAnalytics, - since: currentAnalyticsTimeSpan.cutOffDate, - userId: _pangeaController.matrixState.client.userID!, - ); - return roomEvents?.cast() ?? []; - } - - Future> spaceMemberAnalytics( - Room space, + Future> allMyConstructs( + TimeSpan timeSpan, ) async { - // gets all the summary analytics events for the students - // in a space since the current timespace's cut off date - - // ensure that the participants of the space are loaded - await space.requestParticipants(); - - // TODO switch to using list of futures - final List analyticsEvents = []; - for (final student in space.students) { - final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(currentAnalyticsLang.langCode, student.id); - - if (analyticsRoom != null) { - final List? roomEvents = - await analyticsRoom.getAnalyticsEvents( - type: PangeaEventTypes.summaryAnalytics, - since: currentAnalyticsTimeSpan.cutOffDate, - userId: student.id, - ); - analyticsEvents.addAll( - roomEvents?.cast() ?? [], - ); - } - } - - final List spaceChildrenIds = space.allSpaceChildRoomIds; - - // filter out the analyics events that don't belong to the space's children - final List allAnalyticsEvents = []; - for (final analyticsEvent in analyticsEvents) { - analyticsEvent.content.messages.removeWhere( - (msg) => !spaceChildrenIds.contains(msg.chatId), - ); - allAnalyticsEvents.add(analyticsEvent); - } - - return allAnalyticsEvents; - } - - ChartAnalyticsModel? getAnalyticsLocal({ - TimeSpan? timeSpan, - required AnalyticsSelected defaultSelected, - AnalyticsSelected? selected, - bool forceUpdate = false, - bool updateExpired = false, - DateTime? lastUpdated, - }) { - timeSpan ??= currentAnalyticsTimeSpan; - final int index = _cachedAnalyticsModels.indexWhere( - (e) => - (e.timeSpan == timeSpan) && - (e.defaultSelected.id == defaultSelected.id) && - (e.defaultSelected.type == defaultSelected.type) && - (e.selected?.id == selected?.id) && - (e.selected?.type == selected?.type) && - (e.langCode == currentAnalyticsLang.langCode), - ); - - if (index != -1) { - if ((updateExpired && _cachedAnalyticsModels[index].isExpired) || - forceUpdate || - _cachedAnalyticsModels[index].needsUpdate(lastUpdated)) { - _cachedAnalyticsModels.removeAt(index); - } else { - return _cachedAnalyticsModels[index].chartAnalyticsModel; - } - } - - return null; - } - - void cacheAnalytics({ - required ChartAnalyticsModel chartAnalyticsModel, - required AnalyticsSelected defaultSelected, - AnalyticsSelected? selected, - TimeSpan? timeSpan, - }) { - _cachedAnalyticsModels.add( - AnalyticsCacheModel( - timeSpan: timeSpan ?? currentAnalyticsTimeSpan, - chartAnalyticsModel: chartAnalyticsModel, - defaultSelected: defaultSelected, - selected: selected, - langCode: currentAnalyticsLang.langCode, - ), - ); - } - - List filterStudentAnalytics( - List unfiltered, - String? studentId, - ) { - final List filtered = - List.from(unfiltered); - filtered.removeWhere((e) => e.event.senderId != studentId); - return filtered; - } - - Future> filterRoomAnalytics( - List unfiltered, - String? roomID, - ) async { - List filtered = [...unfiltered]; - Room? room; - if (roomID != null) { - room = _pangeaController.matrixState.client.getRoomById(roomID); - if (room?.isSpace == true) { - return await filterSpaceAnalytics(unfiltered, roomID); - } - } - - filtered = filtered - .where( - (e) => (e.content).messages.any((u) => u.chatId == roomID), - ) - .toList(); - filtered.forEachIndexed( - (i, _) => (filtered[i].content).messages.removeWhere( - (u) => u.chatId != roomID, - ), - ); - return filtered; - } - - Future> filterPrivateChatAnalytics( - List unfiltered, - Room space, - ) async { - final List privateChatIds = space.allSpaceChildRoomIds; - final List lastFetched = await getLatestSpaceHierarchy(space.id); - for (final id in lastFetched) { - privateChatIds.removeWhere((e) => e == id); - } - - List filtered = - List.from(unfiltered); - filtered = filtered.where((e) { - return (e.content).messages.any( - (u) => privateChatIds.contains(u.chatId), - ); - }).toList(); - filtered.forEachIndexed( - (i, _) => (filtered[i].content).messages.removeWhere( - (u) => !privateChatIds.contains(u.chatId), - ), - ); - return filtered; - } - - Future> filterSpaceAnalytics( - List unfiltered, - String spaceId, - ) async { - final List chatIds = await getLatestSpaceHierarchy(spaceId); - List filtered = - List.from(unfiltered); - - filtered = filtered - .where( - (e) => e.content.messages.any((u) => chatIds.contains(u.chatId)), - ) - .toList(); - - filtered.forEachIndexed( - (i, _) => (filtered[i].content).messages.removeWhere( - (u) => !chatIds.contains(u.chatId), - ), - ); - return filtered; - } - - Future> filterAnalytics({ - required List unfilteredAnalytics, - required AnalyticsSelected defaultSelected, - Room? space, - AnalyticsSelected? selected, - }) async { - for (int i = 0; i < unfilteredAnalytics.length; i++) { - unfilteredAnalytics[i].content.messages.removeWhere( - (record) => record.time.isBefore( - currentAnalyticsTimeSpan.cutOffDate, - ), - ); - } - - switch (selected?.type) { - case null: - return unfilteredAnalytics; - case AnalyticsEntryType.student: - if (defaultSelected.type != AnalyticsEntryType.space) { - throw Exception( - "student filtering not available for default filter ${defaultSelected.type}", - ); - } - return filterStudentAnalytics(unfilteredAnalytics, selected?.id); - case AnalyticsEntryType.room: - return filterRoomAnalytics(unfilteredAnalytics, selected?.id); - case AnalyticsEntryType.privateChats: - if (defaultSelected.type == AnalyticsEntryType.student) { - throw "private chat filtering not available for my analytics"; - } - if (space == null) { - throw "space is null in filterAnalytics with selected type privateChats"; - } - return await filterPrivateChatAnalytics( - unfilteredAnalytics, - space, - ); - case AnalyticsEntryType.space: - return await filterSpaceAnalytics(unfilteredAnalytics, selected!.id); - default: - throw Exception("invalid filter type - ${selected?.type}"); - } - } - - Future getAnalytics({ - required AnalyticsSelected defaultSelected, - AnalyticsSelected? selected, - bool forceUpdate = false, - }) async { - try { - await _pangeaController.matrixState.client.roomsLoading; - - // if the user is looking at space analytics, then fetch the space - Room? space; - if (defaultSelected.type == AnalyticsEntryType.space) { - space = _pangeaController.matrixState.client.getRoomById( - defaultSelected.id, - ); - if (space == null) { - ErrorHandler.logError( - m: "space not found in getAnalytics", - data: { - "defaultSelected": defaultSelected, - "selected": selected, - }, - ); - return ChartAnalyticsModel( - msgs: [], - timeSpan: currentAnalyticsTimeSpan, - ); - } - } - - DateTime? lastUpdated; - if (defaultSelected.type != AnalyticsEntryType.space) { - // if default selected view is my analytics, check for the last - // time the logged in user updated their analytics events - // this gets passed to getAnalyticsLocal to determine if the cached - // entry is out-of-date - lastUpdated = await myAnalyticsLastUpdated( - PangeaEventTypes.summaryAnalytics, - ); - } else { - // else, get the last time a student in the space updated their analytics - lastUpdated = await spaceAnalyticsLastUpdated( - PangeaEventTypes.summaryAnalytics, - space!, - ); - } - - final ChartAnalyticsModel? local = getAnalyticsLocal( - defaultSelected: defaultSelected, - selected: selected, - forceUpdate: forceUpdate, - lastUpdated: lastUpdated, - ); - if (local != null && !forceUpdate) { - debugPrint("returning local analytics"); - return local; - } - debugPrint("fetching new analytics"); - - // get all the relevant summary analytics events for the current timespan - final List summaryEvents = - defaultSelected.type == AnalyticsEntryType.space - ? await spaceMemberAnalytics(space!) - : await mySummaryAnalytics(); - - // filter out the analytics events based on filters the user has chosen - final List filteredAnalytics = - await filterAnalytics( - unfilteredAnalytics: summaryEvents, - defaultSelected: defaultSelected, - space: space, - selected: selected, - ); - - // then create and return the model to be displayed - final ChartAnalyticsModel newModel = ChartAnalyticsModel( - timeSpan: currentAnalyticsTimeSpan, - msgs: filteredAnalytics - .map((event) => event.content.messages) - .expand((msgs) => msgs) - .toList(), - ); - - cacheAnalytics( - chartAnalyticsModel: newModel, - defaultSelected: defaultSelected, - selected: selected, - timeSpan: currentAnalyticsTimeSpan, - ); - - return newModel; - } catch (err, s) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: s); - return ChartAnalyticsModel( - msgs: [], - timeSpan: currentAnalyticsTimeSpan, - ); - } - } - - //////////////////////////// CONSTRUCTS //////////////////////////// - - Future> allMyConstructs() async { - final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(currentAnalyticsLang.langCode); + final Room? analyticsRoom = + _pangeaController.matrixState.client.analyticsRoomLocal(langCode); if (analyticsRoom == null) return []; final List? roomEvents = (await analyticsRoom.getAnalyticsEvents( - type: PangeaEventTypes.construct, - since: currentAnalyticsTimeSpan.cutOffDate, + since: timeSpan.cutOffDate, userId: _pangeaController.matrixState.client.userID!, )) ?.cast(); final List allConstructs = roomEvents ?? []; - final List adminSpaceRooms = - await _pangeaController.matrixState.client.teacherRoomIds; - for (final construct in allConstructs) { - construct.content.uses.removeWhere( - (use) => adminSpaceRooms.contains(use.chatId), - ); - } - return allConstructs .where((construct) => construct.content.uses.isNotEmpty) .toList(); @@ -541,17 +163,17 @@ class AnalyticsController extends BaseController { Future> allSpaceMemberConstructs( Room space, + TimeSpan timeSpan, ) async { await space.requestParticipants(); final List constructEvents = []; for (final student in space.students) { final Room? analyticsRoom = _pangeaController.matrixState.client - .analyticsRoomLocal(currentAnalyticsLang.langCode, student.id); + .analyticsRoomLocal(langCode, student.id); if (analyticsRoom != null) { final List? roomEvents = (await analyticsRoom.getAnalyticsEvents( - type: PangeaEventTypes.construct, - since: currentAnalyticsTimeSpan.cutOffDate, + since: timeSpan.cutOffDate, userId: student.id, )) ?.cast(); @@ -600,8 +222,9 @@ class AnalyticsController extends BaseController { Room space, ) async { final List privateChatIds = space.allSpaceChildRoomIds; - final List lastFetched = await getLatestSpaceHierarchy(space.id); - for (final id in lastFetched) { + final resp = await space.client.getSpaceHierarchy(space.id); + final List chatIds = resp.rooms.map((room) => room.roomId).toList(); + for (final id in chatIds) { privateChatIds.removeWhere((e) => e == id); } final List filtered = @@ -618,7 +241,8 @@ class AnalyticsController extends BaseController { List unfilteredConstructs, Room space, ) async { - final List chatIds = await getLatestSpaceHierarchy(space.id); + final resp = await space.client.getSpaceHierarchy(space.id); + final List chatIds = resp.rooms.map((room) => room.roomId).toList(); final List filtered = List.from(unfilteredConstructs); @@ -633,10 +257,10 @@ class AnalyticsController extends BaseController { List? getConstructsLocal({ required TimeSpan timeSpan, - required ConstructTypeEnum constructType, required AnalyticsSelected defaultSelected, AnalyticsSelected? selected, DateTime? lastUpdated, + ConstructTypeEnum? constructType, }) { final index = _cachedConstructs.indexWhere( (e) => @@ -646,7 +270,7 @@ class AnalyticsController extends BaseController { e.defaultSelected.type == defaultSelected.type && e.selected?.id == selected?.id && e.selected?.type == selected?.type && - e.langCode == currentAnalyticsLang.langCode, + e.langCode == langCode, ); if (index > -1) { @@ -661,29 +285,31 @@ class AnalyticsController extends BaseController { } void cacheConstructs({ - required ConstructTypeEnum constructType, required List events, required AnalyticsSelected defaultSelected, + required TimeSpan timeSpan, AnalyticsSelected? selected, + ConstructTypeEnum? constructType, }) { final entry = ConstructCacheEntry( - timeSpan: currentAnalyticsTimeSpan, + timeSpan: timeSpan, type: constructType, events: List.from(events), defaultSelected: defaultSelected, selected: selected, - langCode: currentAnalyticsLang.langCode, + langCode: langCode, ); _cachedConstructs.add(entry); } Future> getMyConstructs({ required AnalyticsSelected defaultSelected, - required ConstructTypeEnum constructType, + required TimeSpan timeSpan, + ConstructTypeEnum? constructType, AnalyticsSelected? selected, }) async { final List unfilteredConstructs = - await allMyConstructs(); + await allMyConstructs(timeSpan); final Room? space = selected?.type == AnalyticsEntryType.space ? _pangeaController.matrixState.client.getRoomById(selected!.id) @@ -694,18 +320,21 @@ class AnalyticsController extends BaseController { space: space, defaultSelected: defaultSelected, selected: selected, + timeSpan: timeSpan, ); } Future> getSpaceConstructs({ - required ConstructTypeEnum constructType, required Room space, required AnalyticsSelected defaultSelected, + required TimeSpan timeSpan, AnalyticsSelected? selected, + ConstructTypeEnum? constructType, }) async { final List unfilteredConstructs = await allSpaceMemberConstructs( space, + timeSpan, ); return filterConstructs( @@ -713,12 +342,14 @@ class AnalyticsController extends BaseController { space: space, defaultSelected: defaultSelected, selected: selected, + timeSpan: timeSpan, ); } Future> filterConstructs({ required List unfilteredConstructs, required AnalyticsSelected defaultSelected, + required TimeSpan timeSpan, Room? space, AnalyticsSelected? selected, }) async { @@ -730,7 +361,7 @@ class AnalyticsController extends BaseController { for (int i = 0; i < unfilteredConstructs.length; i++) { final construct = unfilteredConstructs[i]; construct.content.uses.removeWhere( - (use) => use.timeStamp.isBefore(currentAnalyticsTimeSpan.cutOffDate), + (use) => use.timeStamp.isBefore(timeSpan.cutOffDate), ); } @@ -760,11 +391,12 @@ class AnalyticsController extends BaseController { } Future?> getConstructs({ - required ConstructTypeEnum constructType, required AnalyticsSelected defaultSelected, + required TimeSpan timeSpan, AnalyticsSelected? selected, bool removeIT = true, bool forceUpdate = false, + ConstructTypeEnum? constructType, }) async { debugPrint("getting constructs"); await _pangeaController.matrixState.client.roomsLoading; @@ -792,19 +424,16 @@ class AnalyticsController extends BaseController { // time the logged in user updated their analytics events // this gets passed to getAnalyticsLocal to determine if the cached // entry is out-of-date - lastUpdated = await myAnalyticsLastUpdated( - PangeaEventTypes.construct, - ); + lastUpdated = await myAnalyticsLastUpdated(); } else { // else, get the last time a student in the space updated their analytics lastUpdated = await spaceAnalyticsLastUpdated( - PangeaEventTypes.construct, space!, ); } final List? local = getConstructsLocal( - timeSpan: currentAnalyticsTimeSpan, + timeSpan: timeSpan, constructType: constructType, defaultSelected: defaultSelected, selected: selected, @@ -821,12 +450,14 @@ class AnalyticsController extends BaseController { constructType: constructType, defaultSelected: defaultSelected, selected: selected, + timeSpan: timeSpan, ) : await getSpaceConstructs( constructType: constructType, space: space, defaultSelected: defaultSelected, selected: selected, + timeSpan: timeSpan, ); if (removeIT) { @@ -846,6 +477,7 @@ class AnalyticsController extends BaseController { events: filteredConstructs, defaultSelected: defaultSelected, selected: selected, + timeSpan: timeSpan, ); } @@ -889,32 +521,15 @@ abstract class CacheEntry { } class ConstructCacheEntry extends CacheEntry { - final ConstructTypeEnum type; + final ConstructTypeEnum? type; final List events; ConstructCacheEntry({ - required this.type, required this.events, required super.timeSpan, required super.langCode, required super.defaultSelected, + this.type, super.selected, }); } - -class AnalyticsCacheModel extends CacheEntry { - final ChartAnalyticsModel chartAnalyticsModel; - - AnalyticsCacheModel({ - required this.chartAnalyticsModel, - required super.timeSpan, - required super.langCode, - required super.defaultSelected, - super.selected, - }); - - @override - bool get isExpired => - DateTime.now().difference(_createdAt).inMinutes > - ClassDefaultValues.minutesDelayToMakeNewChartAnalytics; -} diff --git a/lib/pangea/controllers/my_analytics_controller.dart b/lib/pangea/controllers/my_analytics_controller.dart index 199d640ab..d92c2e48d 100644 --- a/lib/pangea/controllers/my_analytics_controller.dart +++ b/lib/pangea/controllers/my_analytics_controller.dart @@ -1,28 +1,48 @@ import 'dart:async'; -import 'dart:developer'; import 'package:fluffychat/pangea/constants/local.key.dart'; import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; +import 'package:fluffychat/pangea/controllers/base_controller.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_record_event.dart'; +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; +import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; -import 'package:fluffychat/pangea/models/analytics/summary_analytics_model.dart'; +import 'package:fluffychat/pangea/models/choreo_record.dart'; +import 'package:fluffychat/pangea/models/pangea_token_model.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; +import 'package:fluffychat/pangea/models/representation_content_model.dart'; +import 'package:fluffychat/pangea/models/tokens_event_content_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; +import 'package:matrix/src/utils/cached_stream_controller.dart'; -import '../extensions/client_extension/client_extension.dart'; -import '../extensions/pangea_room_extension/pangea_room_extension.dart'; +enum AnalyticsUpdateType { server, local } /// handles the processing of analytics for /// 1) messages sent by the user and /// 2) constructs used by the user, both in sending messages and doing practice activities -class MyAnalyticsController { +class MyAnalyticsController extends BaseController { late PangeaController _pangeaController; + CachedStreamController analyticsUpdateStream = + CachedStreamController(); + StreamSubscription? _messageSendSubscription; Timer? _updateTimer; + Client get _client => _pangeaController.matrixState.client; + + String? get userL2 => _pangeaController.languageController.activeL2Code(); + + /// the last time that matrix analytics events were updated for the user's current l2 + DateTime? lastUpdated; + + /// Last updated completer. Used to wait for the last + /// updated time to be set before setting analytics data. + Completer lastUpdatedCompleter = Completer(); + /// the max number of messages that will be cached before /// an automatic update is triggered final int _maxMessagesCached = 10; @@ -37,173 +57,253 @@ class MyAnalyticsController { _pangeaController = pangeaController; } - /// adds the listener that handles when to run automatic updates - /// to analytics - either after a certain number of messages sent - /// received or after a certain amount of time [_timeSinceUpdate] without an update - Future initialize() async { - final lastUpdated = await _refreshAnalyticsIfOutdated(); + void initialize() { + // Listen to a stream that provides the eventIDs + // of new messages sent by the logged in user + _messageSendSubscription ??= stateStream + .where((data) => data is Map) + .listen((data) => onMessageSent(data as Map)); - // listen for new messages and updateAnalytics timer - // we are doing this in an attempt to update analytics when activitiy is low - // both in messages sent by this client and other clients that you're connected with - // doesn't account for messages sent by other clients that you're not connected with - _client.onSync.stream - .where((SyncUpdate update) => update.rooms?.join != null) - .listen((update) { - updateAnalyticsTimer(update, lastUpdated); - }); + _refreshAnalyticsIfOutdated(); + } + + /// Reset analytics last updated time to null. + @override + void dispose() { + _updateTimer?.cancel(); + lastUpdated = null; + lastUpdatedCompleter = Completer(); + _messageSendSubscription?.cancel(); + _messageSendSubscription = null; + _refreshAnalyticsIfOutdated(); + clearMessagesSinceUpdate(); } /// If analytics haven't been updated in the last day, update them - Future _refreshAnalyticsIfOutdated() async { - DateTime? lastUpdated = await _pangeaController.analytics - .myAnalyticsLastUpdated(PangeaEventTypes.summaryAnalytics); - final DateTime yesterday = DateTime.now().subtract(_timeSinceUpdate); + Future _refreshAnalyticsIfOutdated() async { + // don't set anything is the user is not logged in + if (_pangeaController.matrixState.client.userID == null) return; + try { + // if lastUpdated hasn't been set yet, set it + lastUpdated ??= + await _pangeaController.analytics.myAnalyticsLastUpdated(); + } catch (err, s) { + ErrorHandler.logError( + s: s, + e: err, + m: "Failed to get last updated time for analytics", + ); + } finally { + // if this is the initial load, complete the lastUpdatedCompleter + if (!lastUpdatedCompleter.isCompleted) { + lastUpdatedCompleter.complete(lastUpdated); + } + } + final DateTime yesterday = DateTime.now().subtract(_timeSinceUpdate); if (lastUpdated?.isBefore(yesterday) ?? true) { debugPrint("analytics out-of-date, updating"); await updateAnalytics(); - lastUpdated = await _pangeaController.analytics - .myAnalyticsLastUpdated(PangeaEventTypes.summaryAnalytics); - } - return lastUpdated; - } - - Client get _client => _pangeaController.matrixState.client; - - /// Given an update from sync stream, check if the update contains - /// messages for which analytics will be saved. If so, reset the timer - /// and add the event ID to the cache of un-added event IDs - void updateAnalyticsTimer(SyncUpdate update, DateTime? lastUpdated) { - for (final entry in update.rooms!.join!.entries) { - final Room room = _client.getRoomById(entry.key)!; - - // get the new events in this sync that are messages - final List? events = entry.value.timeline?.events - ?.map((event) => Event.fromMatrixEvent(event, room)) - .where((event) => hasUserAnalyticsToCache(event, lastUpdated)) - .toList(); - - // add their event IDs to the cache of un-added event IDs - if (events == null || events.isEmpty) continue; - for (final event in events) { - addMessageSinceUpdate(event.eventId); - } - - // cancel the last timer that was set on message event and - // reset it to fire after _minutesBeforeUpdate minutes - _updateTimer?.cancel(); - _updateTimer = Timer(Duration(minutes: _minutesBeforeUpdate), () { - debugPrint("timer fired, updating analytics"); - updateAnalytics(); - }); } } - // checks if event from sync update is a message that should have analytics - bool hasUserAnalyticsToCache(Event event, DateTime? lastUpdated) { - return event.senderId == _client.userID && - (lastUpdated == null || event.originServerTs.isAfter(lastUpdated)) && - event.type == EventTypes.Message && - event.messageType == MessageTypes.Text && - !(event.eventId.contains("web") && - !(event.eventId.contains("android")) && - !(event.eventId.contains("iOS"))); - } + /// Given the data from a newly sent message, format and cache + /// the message's construct data locally and reset the update timer + void onMessageSent(Map data) { + // cancel the last timer that was set on message event and + // reset it to fire after _minutesBeforeUpdate minutes + _updateTimer?.cancel(); + _updateTimer = Timer(Duration(minutes: _minutesBeforeUpdate), () { + debugPrint("timer fired, updating analytics"); + updateAnalytics(); + }); - // adds an event ID to the cache of un-added event IDs - // if the event IDs isn't already added - void addMessageSinceUpdate(String eventId) { - try { - final List currentCache = messagesSinceUpdate; - if (!currentCache.contains(eventId)) { - currentCache.add(eventId); - _pangeaController.pStoreService.save( - PLocalKey.messagesSinceUpdate, - currentCache, - ); - } + // extract the relevant data about this message + final String? eventID = data['eventID']; + final String? roomID = data['roomID']; + final String? eventType = data['eventType']; + final PangeaRepresentation? originalSent = data['originalSent']; + final PangeaMessageTokens? tokensSent = data['tokensSent']; + final ChoreoRecord? choreo = data['choreo']; + final PracticeActivityEvent? practiceActivity = data['practiceActivity']; + final PracticeActivityRecordModel? recordModel = data['recordModel']; - // if the cached has reached if max-length, update analytics - if (messagesSinceUpdate.length > _maxMessagesCached) { - debugPrint("reached max messages, updating"); - updateAnalytics(); - } - } catch (exception, stackTrace) { - ErrorHandler.logError( - e: PangeaWarningError("Failed to add message since update: $exception"), - s: stackTrace, - m: 'Failed to add message since update for eventId: $eventId', + if (roomID == null || eventID == null) return; + + // convert that data into construct uses and add it to the cache + final metadata = ConstructUseMetaData( + roomId: roomID, + eventId: eventID, + timeStamp: DateTime.now(), + ); + + final List constructs = getDraftUses(roomID); + + if (eventType == EventTypes.Message) { + final grammarConstructs = + choreo?.grammarConstructUses(metadata: metadata); + final vocabUses = tokensSent != null + ? originalSent?.vocabUses( + choreo: choreo, + tokens: tokensSent.tokens, + metadata: metadata, + ) + : null; + constructs.addAll([ + ...(grammarConstructs ?? []), + ...(vocabUses ?? []), + ]); + } + + if (eventType == PangeaEventTypes.activityRecord && + practiceActivity != null) { + final activityConstructs = recordModel?.uses( + practiceActivity, + metadata: metadata, ); - Sentry.captureException( - exception, - stackTrace: stackTrace, - withScope: (scope) { - scope.setExtra( - 'extra_info', - 'Failed during addMessageSinceUpdate with eventId: $eventId', - ); - scope.setTag('where', 'addMessageSinceUpdate'); + constructs.addAll(activityConstructs ?? []); + } + + _pangeaController.analytics + .filterConstructs(unfilteredConstructs: constructs) + .then((filtered) { + if (filtered.isEmpty) return; + filtered.addAll(getDraftUses(roomID)); + final level = _pangeaController.analytics.level; + addLocalMessage(eventID, filtered).then( + (_) { + clearDraftUses(roomID); + afterAddLocalMessages(level); }, ); - } + }); } - // called before updating analytics - void clearMessagesSinceUpdate() { - _pangeaController.pStoreService.save( - PLocalKey.messagesSinceUpdate, - [], + void addDraftUses( + List tokens, + String roomID, + ConstructUseTypeEnum useType, + ) { + final metadata = ConstructUseMetaData( + roomId: roomID, + timeStamp: DateTime.now(), + ); + + final uses = tokens + .where((token) => token.lemma.saveVocab) + .map( + (token) => OneConstructUse( + useType: useType, + lemma: token.lemma.text, + form: token.lemma.form, + constructType: ConstructTypeEnum.vocab, + metadata: metadata, + ), + ) + .toList(); + + for (final token in tokens) { + for (final entry in token.morph.entries) { + uses.add( + OneConstructUse( + useType: useType, + lemma: entry.value, + categories: [entry.key], + constructType: ConstructTypeEnum.morph, + metadata: metadata, + ), + ); + } + } + + final level = _pangeaController.analytics.level; + addLocalMessage('draft$roomID', uses).then( + (_) => afterAddLocalMessages(level), ); } - // a local cache of eventIds for messages sent since the last update - // it's possible for this cache to be invalid or deleted - // It's a proxy measure for messages sent since last update - List get messagesSinceUpdate { + List getDraftUses(String roomID) { + final currentCache = _pangeaController.analytics.messagesSinceUpdate; + return currentCache['draft$roomID'] ?? []; + } + + void clearDraftUses(String roomID) { + final currentCache = _pangeaController.analytics.messagesSinceUpdate; + currentCache.remove('draft$roomID'); + setMessagesSinceUpdate(currentCache); + } + + /// Add a list of construct uses for a new message to the local + /// cache of recently sent messages + Future addLocalMessage( + String eventID, + List constructs, + ) async { try { - Logs().d('Reading messages since update from local storage'); - final dynamic locallySaved = _pangeaController.pStoreService.read( - PLocalKey.messagesSinceUpdate, - ); - if (locallySaved == null) { - Logs().d('No locally saved messages found, initializing empty list.'); - _pangeaController.pStoreService.save( - PLocalKey.messagesSinceUpdate, - [], - ); - return []; - } - return locallySaved.cast(); - } catch (exception, stackTrace) { + final currentCache = _pangeaController.analytics.messagesSinceUpdate; + constructs.addAll(currentCache[eventID] ?? []); + currentCache[eventID] = constructs; + + await setMessagesSinceUpdate(currentCache); + } catch (e, s) { ErrorHandler.logError( - e: PangeaWarningError( - "Failed to get messages since update: $exception", - ), - s: stackTrace, - m: 'Failed to retrieve messages since update', + e: PangeaWarningError("Failed to add message since update: $e"), + s: s, + m: 'Failed to add message since update for eventId: $eventID', ); - Sentry.captureException( - exception, - stackTrace: stackTrace, - withScope: (scope) { - scope.setExtra( - 'extra_info', - 'Error during messagesSinceUpdate getter', - ); - scope.setTag('where', 'messagesSinceUpdate'); - }, - ); - _pangeaController.pStoreService.save( - PLocalKey.messagesSinceUpdate, - [], - ); - return []; } } + /// Handles cleanup after adding a new message to the local cache. + /// If the addition brought the total number of messages in the cache + /// to the max, or if the addition triggered a level-up, update the analytics. + /// Otherwise, add a local update to the alert stream. + void afterAddLocalMessages(int prevLevel) { + if (_pangeaController.analytics.messagesSinceUpdate.length > + _maxMessagesCached) { + debugPrint("reached max messages, updating"); + updateAnalytics(); + return; + } + + final int newLevel = _pangeaController.analytics.level; + newLevel > prevLevel + ? updateAnalytics() + : analyticsUpdateStream.add(AnalyticsUpdateType.local); + } + + /// Clears the local cache of recently sent constructs. Called before updating analytics + void clearMessagesSinceUpdate() { + _pangeaController.pStoreService.delete(PLocalKey.messagesSinceUpdate); + } + + /// Save the local cache of recently sent constructs to the local storage + Future setMessagesSinceUpdate( + Map> cache, + ) async { + final formattedCache = {}; + for (final entry in cache.entries) { + final constructJsons = entry.value.map((e) => e.toJson()).toList(); + formattedCache[entry.key] = constructJsons; + } + await _pangeaController.pStoreService.save( + PLocalKey.messagesSinceUpdate, + formattedCache, + ); + } + + /// Prevent concurrent updates to analytics Completer? _updateCompleter; + + /// Updates learning analytics. + /// + /// This method is responsible for updating the analytics. It first checks if an update is already in progress + /// by checking the completion status of the [_updateCompleter]. If an update is already in progress, it waits + /// for the completion of the previous update and returns. Otherwise, it creates a new [_updateCompleter] and + /// proceeds with the update process. If the update is successful, it clears any messages that were received + /// since the last update and notifies the [analyticsUpdateStream]. Future updateAnalytics() async { + if (_pangeaController.matrixState.client.userID == null) return; if (!(_updateCompleter?.isCompleted ?? true)) { await _updateCompleter!.future; return; @@ -212,6 +312,9 @@ class MyAnalyticsController { try { await _updateAnalytics(); clearMessagesSinceUpdate(); + + lastUpdated = DateTime.now(); + analyticsUpdateStream.add(AnalyticsUpdateType.server); } catch (err, s) { ErrorHandler.logError( e: err, @@ -224,136 +327,24 @@ class MyAnalyticsController { } } - String? get userL2 => _pangeaController.languageController.activeL2Code(); - - /// top level analytics sending function. Gather recent messages and activity records, - /// convert them into the correct formats, and send them to the analytics room + /// Updates the analytics by sending cached analytics data to the analytics room. + /// The analytics room is determined based on the user's current target language. Future _updateAnalytics() async { + // if there's no cached construct data, there's nothing to send + final cachedConstructs = _pangeaController.analytics.messagesSinceUpdate; + final bool onlyDraft = cachedConstructs.length == 1 && + cachedConstructs.keys.single.startsWith('draft'); + if (cachedConstructs.isEmpty || onlyDraft) return; + // if missing important info, don't send analytics. Could happen if user just signed up. if (userL2 == null || _client.userID == null) return; // analytics room for the user and current target language final Room? analyticsRoom = await _client.getMyAnalyticsRoom(userL2!); - // get the last time analytics were updated for this room - final DateTime? l2AnalyticsLastUpdated = - await analyticsRoom?.analyticsLastUpdated( - PangeaEventTypes.summaryAnalytics, - _client.userID!, + // and send cached analytics data to the room + await analyticsRoom?.sendConstructsEvent( + _pangeaController.analytics.locallyCachedSentConstructs, ); - - // all chats in which user is a student - final List chats = _client.rooms - .where((room) => !room.isSpace && !room.isAnalyticsRoom) - .toList(); - - // get the recent message events and activity records for each chat - final List>> recentMsgFutures = []; - final List>> recentActivityFutures = []; - for (final Room chat in chats) { - recentMsgFutures.add( - chat.getEventsBySender( - type: EventTypes.Message, - sender: _client.userID!, - since: l2AnalyticsLastUpdated, - ), - ); - recentActivityFutures.add( - chat.getEventsBySender( - type: PangeaEventTypes.activityRecord, - sender: _client.userID!, - since: l2AnalyticsLastUpdated, - ), - ); - } - final List> recentMsgs = - (await Future.wait(recentMsgFutures)).toList(); - final List recentActivityRecords = - (await Future.wait(recentActivityFutures)) - .expand((e) => e) - .map((event) => PracticeActivityRecordEvent(event: event)) - .toList(); - - // get the timelines for each chat - final List> timelineFutures = []; - for (final chat in chats) { - timelineFutures.add( - chat.timeline == null - ? chat.getTimeline() - : Future.value(chat.timeline), - ); - } - final List timelines = await Future.wait(timelineFutures); - final Map timelineMap = - Map.fromIterables(chats.map((e) => e.id), timelines); - - //convert into PangeaMessageEvents - final List> recentPangeaMessageEvents = []; - for (final (index, eventList) in recentMsgs.indexed) { - recentPangeaMessageEvents.add( - eventList - .map( - (event) => PangeaMessageEvent( - event: event, - timeline: timelines[index], - ownMessage: true, - ), - ) - .toList(), - ); - } - - final List allRecentMessages = - recentPangeaMessageEvents.expand((e) => e).toList(); - - final List summaryContent = - SummaryAnalyticsModel.formatSummaryContent(allRecentMessages); - // if there's new content to be sent, or if lastUpdated hasn't been - // set yet for this room, send the analytics events - if (summaryContent.isNotEmpty || l2AnalyticsLastUpdated == null) { - await analyticsRoom?.sendSummaryAnalyticsEvent( - summaryContent, - ); - } - - // get constructs for messages - final List recentConstructUses = []; - for (final PangeaMessageEvent message in allRecentMessages) { - recentConstructUses.addAll(message.allConstructUses); - } - - // get constructs for practice activities - final List>> constructFutures = []; - for (final PracticeActivityRecordEvent activity in recentActivityRecords) { - final Timeline? timeline = timelineMap[activity.event.roomId!]; - if (timeline == null) { - debugger(when: kDebugMode); - ErrorHandler.logError( - m: "PracticeActivityRecordEvent has null timeline", - data: activity.event.toJson(), - ); - continue; - } - constructFutures.add(activity.uses(timeline)); - } - final List> constructLists = - await Future.wait(constructFutures); - - recentConstructUses.addAll(constructLists.expand((e) => e)); - - //TODO - confirm that this is the correct construct content - // debugger( - // when: kDebugMode, - // ); - // ; debugger( - // when: kDebugMode && - // (allRecentMessages.isNotEmpty || recentActivityRecords.isNotEmpty), - // ); - - if (recentConstructUses.isNotEmpty) { - await analyticsRoom?.sendConstructsEvent( - recentConstructUses, - ); - } } } diff --git a/lib/pangea/controllers/pangea_controller.dart b/lib/pangea/controllers/pangea_controller.dart index 79222bbed..243a49174 100644 --- a/lib/pangea/controllers/pangea_controller.dart +++ b/lib/pangea/controllers/pangea_controller.dart @@ -6,6 +6,7 @@ import 'package:fluffychat/pangea/constants/class_default_values.dart'; import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/controllers/class_controller.dart'; import 'package:fluffychat/pangea/controllers/contextual_definition_controller.dart'; +import 'package:fluffychat/pangea/controllers/get_analytics_controller.dart'; import 'package:fluffychat/pangea/controllers/language_controller.dart'; import 'package:fluffychat/pangea/controllers/language_detection_controller.dart'; import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; @@ -35,7 +36,6 @@ import '../../config/app_config.dart'; import '../utils/firebase_analytics.dart'; import '../utils/p_store.dart'; import 'it_feedback_controller.dart'; -import 'message_analytics_controller.dart'; class PangeaController { ///pangeaControllers @@ -43,7 +43,8 @@ class PangeaController { late LanguageController languageController; late ClassController classController; late PermissionsController permissionsController; - late AnalyticsController analytics; + // late AnalyticsController analytics; + late GetAnalyticsController analytics; late MyAnalyticsController myAnalytics; late WordController wordNet; late MessageDataController messageData; @@ -91,7 +92,8 @@ class PangeaController { languageController = LanguageController(this); classController = ClassController(this); permissionsController = PermissionsController(this); - analytics = AnalyticsController(this); + // analytics = AnalyticsController(this); + analytics = GetAnalyticsController(this); myAnalytics = MyAnalyticsController(this); messageData = MessageDataController(this); wordNet = WordController(this); @@ -139,6 +141,19 @@ class PangeaController { /// check user information if not found then redirect to Date of birth page _handleLoginStateChange(LoginState state) { + switch (state) { + case LoginState.loggedOut: + case LoginState.softLoggedOut: + // Reset cached analytics data + MatrixState.pangeaController.myAnalytics.dispose(); + MatrixState.pangeaController.analytics.dispose(); + break; + case LoginState.loggedIn: + // Initialize analytics data + MatrixState.pangeaController.myAnalytics.initialize(); + MatrixState.pangeaController.analytics.initialize(); + break; + } if (state != LoginState.loggedIn) { _logOutfromPangea(); } diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index 035b122e4..5ee8672ff 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -70,9 +70,12 @@ class UserController extends BaseController { } /// Updates the user's profile with the given [update] function and saves it. - void updateProfile(Profile Function(Profile) update) { + Future updateProfile( + Profile Function(Profile) update, { + waitForDataInSync = false, + }) async { final Profile updatedProfile = update(profile); - updatedProfile.saveProfileData(); + await updatedProfile.saveProfileData(waitForDataInSync: waitForDataInSync); } /// Creates a new profile for the user with the given date of birth. diff --git a/lib/pangea/enum/construct_type_enum.dart b/lib/pangea/enum/construct_type_enum.dart index 7db7f9cd5..2b346b235 100644 --- a/lib/pangea/enum/construct_type_enum.dart +++ b/lib/pangea/enum/construct_type_enum.dart @@ -1,6 +1,9 @@ +import 'package:fluffychat/pangea/constants/analytics_constants.dart'; + enum ConstructTypeEnum { grammar, vocab, + morph, } extension ConstructExtension on ConstructTypeEnum { @@ -10,6 +13,19 @@ extension ConstructExtension on ConstructTypeEnum { return 'grammar'; case ConstructTypeEnum.vocab: return 'vocab'; + case ConstructTypeEnum.morph: + return 'morph'; + } + } + + int get maxXPPerLemma { + switch (this) { + case ConstructTypeEnum.grammar: + return 0; + case ConstructTypeEnum.vocab: + return AnalyticsConstants.vocabUseMaxXP; + case ConstructTypeEnum.morph: + return AnalyticsConstants.morphUseMaxXP; } } } @@ -23,6 +39,9 @@ class ConstructTypeUtil { case 'v': case 'vocab': return ConstructTypeEnum.vocab; + case 'm': + case 'morph': + return ConstructTypeEnum.morph; default: return ConstructTypeEnum.vocab; } diff --git a/lib/pangea/enum/progress_indicators_enum.dart b/lib/pangea/enum/progress_indicators_enum.dart new file mode 100644 index 000000000..ae37df389 --- /dev/null +++ b/lib/pangea/enum/progress_indicators_enum.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:material_symbols_icons/symbols.dart'; + +enum ProgressIndicatorEnum { + level, + wordsUsed, + morphsUsed, +} + +extension ProgressIndicatorsExtension on ProgressIndicatorEnum { + IconData get icon { + switch (this) { + case ProgressIndicatorEnum.wordsUsed: + return Icons.text_fields_outlined; + case ProgressIndicatorEnum.morphsUsed: + return Symbols.toys_and_games; + case ProgressIndicatorEnum.level: + return Icons.star; + } + } + + static bool isDarkMode(BuildContext context) => + Theme.of(context).brightness == Brightness.dark; + + Color color(BuildContext context) { + switch (this) { + case ProgressIndicatorEnum.wordsUsed: + return Theme.of(context).brightness == Brightness.dark + ? const Color.fromARGB(255, 169, 183, 237) + : const Color.fromARGB(255, 38, 59, 141); + // case ProgressIndicatorEnum.errorTypes: + // return Theme.of(context).brightness == Brightness.dark + // ? const Color.fromARGB(255, 212, 144, 216) + // : const Color.fromARGB(255, 163, 39, 169); + case ProgressIndicatorEnum.level: + return Theme.of(context).brightness == Brightness.dark + ? const Color.fromARGB(255, 250, 220, 129) + : const Color.fromARGB(255, 255, 208, 67); + case ProgressIndicatorEnum.morphsUsed: + return Theme.of(context).brightness == Brightness.dark + ? const Color.fromARGB(255, 169, 183, 237) + : const Color.fromARGB(255, 38, 59, 141); + } + } + + String tooltip(BuildContext context) { + switch (this) { + case ProgressIndicatorEnum.wordsUsed: + return L10n.of(context)!.vocab; + case ProgressIndicatorEnum.level: + return L10n.of(context)!.level; + case ProgressIndicatorEnum.morphsUsed: + return L10n.of(context)!.grammar; + } + } +} diff --git a/lib/pangea/enum/time_span.dart b/lib/pangea/enum/time_span.dart index ddc9ce32b..4aaca7527 100644 --- a/lib/pangea/enum/time_span.dart +++ b/lib/pangea/enum/time_span.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import '../models/analytics/chart_analytics_model.dart'; - -enum TimeSpan { day, week, month, sixmonths, year } +enum TimeSpan { day, week, month, sixmonths, year, forever } extension TimeSpanFunctions on TimeSpan { String string(BuildContext context) { @@ -35,19 +33,8 @@ extension TimeSpanFunctions on TimeSpan { return 6; case TimeSpan.year: return 12; - } - } - - Duration timeAgo(int index) { - switch (this) { - case TimeSpan.day: - return Duration(hours: index); - case TimeSpan.week: - case TimeSpan.month: - return Duration(days: index); - case TimeSpan.year: - case TimeSpan.sixmonths: - return Duration(days: index * 32); + case TimeSpan.forever: + return 0; } } @@ -65,44 +52,8 @@ extension TimeSpanFunctions on TimeSpan { return DateTime.now().subtract(Duration(days: numberOfIntervals * 30)); case TimeSpan.year: return DateTime.now().subtract(const Duration(days: 365)); + case TimeSpan.forever: + return DateTime(2020); } } - - String getMapKey(DateTime date) { - switch (this) { - case TimeSpan.day: - return date.hour.toString(); - case TimeSpan.week: - return date.weekday.toString(); - case TimeSpan.month: - return date.day.toString(); - case TimeSpan.sixmonths: - case TimeSpan.year: - return date.month.toString(); - } - } - - /// Note: end is same as start!! - Map get emptyIntervals { - final DateTime now = DateTime.now(); - final List numbers = - List.generate(numberOfIntervals, (index) => index); - final Map map = {}; - - // debugger(when: kDebugMode); - for (final index in numbers) { - final timeAgos = timeAgo(index); - final DateTime end = now.subtract(timeAgos); - // debugger(when: end.isBefore(now.subtract(const Duration(days: 30)))); - final String mapKey = getMapKey(end); - // debugger(when: mapKey.toString() == "5"); - map[mapKey] = TimeSeriesInterval( - start: end, - end: end, - totals: TimeSeriesTotals.empty, - ); - } - // debugger(when: kDebugMode); - return map; - } } diff --git a/lib/pangea/extensions/client_extension/client_analytics_extension.dart b/lib/pangea/extensions/client_extension/client_analytics_extension.dart index 381bbba4c..64691f98b 100644 --- a/lib/pangea/extensions/client_extension/client_analytics_extension.dart +++ b/lib/pangea/extensions/client_extension/client_analytics_extension.dart @@ -153,17 +153,4 @@ extension AnalyticsClientExtension on Client { _joinAnalyticsRoomsInAllSpaces(); }); } - - Future> _allAnalyticsRoomsLastUpdated() async { - // get the last updated time for each analytics room - final Map lastUpdatedMap = {}; - for (final analyticsRoom in allMyAnalyticsRooms) { - final DateTime? lastUpdated = await analyticsRoom.analyticsLastUpdated( - PangeaEventTypes.summaryAnalytics, - userID!, - ); - lastUpdatedMap[analyticsRoom.id] = lastUpdated; - } - return lastUpdatedMap; - } } diff --git a/lib/pangea/extensions/client_extension/client_extension.dart b/lib/pangea/extensions/client_extension/client_extension.dart index 7af50d501..0971ab04d 100644 --- a/lib/pangea/extensions/client_extension/client_extension.dart +++ b/lib/pangea/extensions/client_extension/client_extension.dart @@ -2,7 +2,6 @@ import 'dart:developer'; import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; -import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/models/space_model.dart'; @@ -39,15 +38,10 @@ extension PangeaClient on Client { /// and set up those rooms to be joined by other users. void migrateAnalyticsRooms() => _migrateAnalyticsRooms(); - Future> allAnalyticsRoomsLastUpdated() async => - await _allAnalyticsRoomsLastUpdated(); - // spaces List get spacesImTeaching => _spacesImTeaching; - Future> get chatsImAStudentIn async => await _chatsImAStudentIn; - List get spacesImAStudentIn => _spacesImStudyingIn; List get spacesImIn => _spacesImIn; @@ -56,8 +50,6 @@ extension PangeaClient on Client { // general_info - Future> get teacherRoomIds async => await _teacherRoomIds; - Future> get myTeachers async => await _myTeachers; Future getReportsDM(User teacher, Room space) async => diff --git a/lib/pangea/extensions/client_extension/general_info_extension.dart b/lib/pangea/extensions/client_extension/general_info_extension.dart index 41f81442e..777b21474 100644 --- a/lib/pangea/extensions/client_extension/general_info_extension.dart +++ b/lib/pangea/extensions/client_extension/general_info_extension.dart @@ -1,16 +1,6 @@ part of "client_extension.dart"; extension GeneralInfoClientExtension on Client { - Future> get _teacherRoomIds async { - final List adminRoomIds = []; - for (final Room adminSpace in (_spacesImTeaching)) { - adminRoomIds.add(adminSpace.id); - final List adminSpaceRooms = adminSpace.allSpaceChildRoomIds; - adminRoomIds.addAll(adminSpaceRooms); - } - return adminRoomIds; - } - Future> get _myTeachers async { final List teachers = []; for (final classRoom in spacesImIn) { diff --git a/lib/pangea/extensions/client_extension/space_extension.dart b/lib/pangea/extensions/client_extension/space_extension.dart index 89a09a7cd..8d9182d85 100644 --- a/lib/pangea/extensions/client_extension/space_extension.dart +++ b/lib/pangea/extensions/client_extension/space_extension.dart @@ -4,18 +4,6 @@ extension SpaceClientExtension on Client { List get _spacesImTeaching => rooms.where((e) => e.isSpace && e.isRoomAdmin).toList(); - Future> get _chatsImAStudentIn async { - final List nowteacherRoomIds = await teacherRoomIds; - return rooms - .where( - (r) => - !r.isSpace && - !r.isAnalyticsRoom && - !nowteacherRoomIds.contains(r.id), - ) - .toList(); - } - List get _spacesImStudyingIn => rooms.where((e) => e.isSpace && !e.isRoomAdmin).toList(); diff --git a/lib/pangea/extensions/pangea_room_extension/events_extension.dart b/lib/pangea/extensions/pangea_room_extension/events_extension.dart index 182779853..d8e2545ff 100644 --- a/lib/pangea/extensions/pangea_room_extension/events_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/events_extension.dart @@ -282,83 +282,6 @@ extension EventsRoomExtension on Room { ); } - Future> get _messageListForAllChildChats async { - try { - if (!isSpace) return []; - final List spaceChats = spaceChildren - .where((e) => e.roomId != null) - .map((e) => client.getRoomById(e.roomId!)) - .where((element) => element != null) - .cast() - .where((element) => !element.isSpace) - .toList(); - - final List>> msgListFutures = []; - for (final chat in spaceChats) { - msgListFutures.add(chat._messageListForChat); - } - final List> msgLists = - await Future.wait(msgListFutures); - - final List joined = []; - for (final msgList in msgLists) { - joined.addAll(msgList); - } - return joined; - } catch (err) { - // debugger(when: kDebugMode); - rethrow; - } - } - - Future> get _messageListForChat async { - try { - int numberOfSearches = 0; - - if (isSpace) { - throw Exception( - "In messageListForChat with room that is not a chat", - ); - } - final Timeline timeline = this.timeline ?? await getTimeline(); - - while (timeline.canRequestHistory && numberOfSearches < 50) { - await timeline.requestHistory(historyCount: 100); - numberOfSearches += 1; - } - if (timeline.canRequestHistory) { - debugger(when: kDebugMode); - } - - final List msgs = []; - for (final event in timeline.events) { - if (event.senderId == client.userID && - event.type == EventTypes.Message && - event.content['msgtype'] == MessageTypes.Text) { - final PangeaMessageEvent pMsgEvent = PangeaMessageEvent( - event: event, - timeline: timeline, - ownMessage: true, - ); - msgs.add( - RecentMessageRecord( - eventId: event.eventId, - chatId: id, - useType: pMsgEvent.msgUseType, - time: event.originServerTs, - ), - ); - } - } - return msgs; - } catch (err, s) { - if (kDebugMode) rethrow; - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: s); - return []; - } - } - // ConstructEvent? _vocabEventLocal(String lemma) { // if (!isAnalyticsRoom) throw Exception("not an analytics room"); @@ -423,69 +346,51 @@ extension EventsRoomExtension on Room { // } // } - // fetch event of a certain type by a certain sender - // since a certain time or up to a certain amount - Future> getEventsBySender({ - required String type, - required String sender, - DateTime? since, + /// Get a list of events in the room that are of type [PangeaEventTypes.construct] + /// and have the sender as [userID]. If [count] is provided, the function will + /// return at most [count] events. + Future> getRoomAnalyticsEvents({ + String? userID, int? count, }) async { - try { - int numberOfSearches = 0; - final Timeline timeline = this.timeline ?? await getTimeline(); + userID ??= client.userID; + if (userID == null) return []; + GetRoomEventsResponse resp = await client.getRoomEvents( + id, + Direction.b, + limit: count ?? 100, + filter: jsonEncode( + StateFilter( + types: [ + PangeaEventTypes.construct, + ], + senders: [userID], + ), + ), + ); - List relevantEvents() => timeline.events - .where((event) => event.senderId == sender && event.type == type) - .toList(); - - bool reachedEnd() { - if (since != null) { - return relevantEvents().any( - (event) => event.originServerTs.isBefore(since), - ); - } - if (count != null) { - return relevantEvents().length >= count; - } - return false; - } - - while (timeline.canRequestHistory && - !reachedEnd() && - numberOfSearches < 10) { - await timeline.requestHistory(historyCount: 100); - numberOfSearches += 1; - if (reachedEnd()) { - break; - } - } - - final List fetchedEvents = timeline.events - .where((event) => event.senderId == sender && event.type == type) - .toList(); - - if (since != null) { - fetchedEvents.removeWhere( - (event) => event.originServerTs.isBefore(since), - ); - } - - final List events = []; - for (Event event in fetchedEvents) { - if (event.relationshipType == RelationshipTypes.edit) continue; - if (event.hasAggregatedEvents(timeline, RelationshipTypes.edit)) { - event = event.getDisplayEvent(timeline); - } - events.add(event); - } - - return events; - } catch (err, s) { - if (kDebugMode) rethrow; - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: s); - return []; + int numSearches = 0; + while (numSearches < 10 && resp.end != null) { + if (count != null && resp.chunk.length <= count) break; + final nextResp = await client.getRoomEvents( + id, + Direction.b, + limit: count ?? 100, + filter: jsonEncode( + StateFilter( + types: [ + PangeaEventTypes.construct, + ], + senders: [userID], + ), + ), + from: resp.end, + ); + nextResp.chunk.addAll(resp.chunk); + resp = nextResp; + numSearches += 1; } + + return resp.chunk.map((e) => Event.fromMatrixEvent(e, this)).toList(); } } diff --git a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart index c22ba9a23..bf9e10953 100644 --- a/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/pangea_room_extension.dart @@ -9,12 +9,8 @@ import 'package:fluffychat/pangea/constants/language_constants.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/models/analytics/analytics_event.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_event.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; -import 'package:fluffychat/pangea/models/analytics/summary_analytics_event.dart'; -import 'package:fluffychat/pangea/models/analytics/summary_analytics_model.dart'; import 'package:fluffychat/pangea/models/bot_options_model.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; import 'package:fluffychat/pangea/models/space_model.dart'; @@ -80,27 +76,30 @@ extension PangeaRoom on Room { void inviteSpaceTeachersToAnalyticsRooms() => _inviteSpaceTeachersToAnalyticsRooms(); - Future getLastAnalyticsEvent( - String type, - String userId, - ) async => - await _getLastAnalyticsEvent(type, userId); - - Future analyticsLastUpdated(String type, String userId) async { - return await _analyticsLastUpdated(type, userId); + Future analyticsLastUpdated(String userId) async { + return await _analyticsLastUpdated(userId); } - Future?> getAnalyticsEvents({ - required String type, + Future?> getAnalyticsEvents({ required String userId, DateTime? since, }) async => - await _getAnalyticsEvents(type: type, since: since, userId: userId); + await _getAnalyticsEvents(since: since, userId: userId); String? get madeForLang => _madeForLang; bool isMadeForLang(String langCode) => _isMadeForLang(langCode); + /// Sends construct events to the server. + /// + /// The [uses] parameter is a list of [OneConstructUse] objects representing the + /// constructs to be sent. To prevent hitting the maximum event size, the events + /// are chunked into smaller lists. Each chunk is sent as a separate event. + Future sendConstructsEvent( + List uses, + ) async => + await _sendConstructsEvent(uses); + // children_and_parents List get joinedChildren => _joinedChildren; diff --git a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart index 7bdd13743..73371b080 100644 --- a/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart +++ b/lib/pangea/extensions/pangea_room_extension/room_analytics_extension.dart @@ -140,52 +140,20 @@ extension AnalyticsRoomExtension on Room { ); } - Future _getLastAnalyticsEvent( - String type, - String userId, - ) async { - final List events = await getEventsBySender( - type: type, - sender: userId, - count: 10, - ); + Future _analyticsLastUpdated(String userId) async { + final List events = await getRoomAnalyticsEvents(count: 1); if (events.isEmpty) return null; - final Event event = events.first; - AnalyticsEvent? analyticsEvent; - switch (type) { - case PangeaEventTypes.summaryAnalytics: - analyticsEvent = SummaryAnalyticsEvent(event: event); - case PangeaEventTypes.construct: - analyticsEvent = ConstructAnalyticsEvent(event: event); - } - return analyticsEvent; + return events.first.originServerTs; } - Future _analyticsLastUpdated(String type, String userId) async { - final lastEvent = await _getLastAnalyticsEvent(type, userId); - return lastEvent?.event.originServerTs; - } - - Future?> _getAnalyticsEvents({ - required String type, + Future?> _getAnalyticsEvents({ required String userId, DateTime? since, }) async { - final List events = await getEventsBySender( - type: type, - sender: userId, - since: since, - ); - final List analyticsEvents = []; + final events = await getRoomAnalyticsEvents(); + final List analyticsEvents = []; for (final Event event in events) { - switch (type) { - case PangeaEventTypes.summaryAnalytics: - analyticsEvents.add(SummaryAnalyticsEvent(event: event)); - break; - case PangeaEventTypes.construct: - analyticsEvents.add(ConstructAnalyticsEvent(event: event)); - break; - } + analyticsEvents.add(ConstructAnalyticsEvent(event: event)); } return analyticsEvents; @@ -203,26 +171,26 @@ extension AnalyticsRoomExtension on Room { creationContent?.tryGet(ModelKey.oldLangCode) == langCode; } - Future sendSummaryAnalyticsEvent( - List records, - ) async { - final SummaryAnalyticsModel analyticsModel = SummaryAnalyticsModel( - messages: records, - ); - await sendEvent( - analyticsModel.toJson(), - type: PangeaEventTypes.summaryAnalytics, - ); - } - /// Sends construct events to the server. /// /// The [uses] parameter is a list of [OneConstructUse] objects representing the /// constructs to be sent. To prevent hitting the maximum event size, the events /// are chunked into smaller lists. Each chunk is sent as a separate event. - Future sendConstructsEvent( + Future _sendConstructsEvent( List uses, ) async { + // It's possible that the user has no info to send yet, but to prevent trying + // to load the data over and over again, we'll sometimes send an empty event to + // indicate that we have checked and there was no data. + if (uses.isEmpty) { + final constructsModel = ConstructAnalyticsModel(uses: []); + await sendEvent( + constructsModel.toJson(), + type: PangeaEventTypes.construct, + ); + return; + } + // these events can get big, so we chunk them to prevent hitting the max event size. // go through each of the uses being sent and add them to the current chunk until // the size (in bytes) of the current chunk is greater than the max event size, then diff --git a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart index 06462cbea..ce09f003a 100644 --- a/lib/pangea/matrix_event_wrappers/pangea_message_event.dart +++ b/lib/pangea/matrix_event_wrappers/pangea_message_event.dart @@ -2,20 +2,15 @@ import 'dart:convert'; import 'dart:developer'; import 'package:collection/collection.dart'; -import 'package:fluffychat/pangea/constants/choreo_constants.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:fluffychat/pangea/controllers/text_to_speech_controller.dart'; import 'package:fluffychat/pangea/enum/audio_encoding_enum.dart'; -import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; -import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_representation_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:fluffychat/pangea/models/choreo_record.dart'; -import 'package:fluffychat/pangea/models/lemma.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; -import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/representation_content_model.dart'; import 'package:fluffychat/pangea/models/space_model.dart'; import 'package:fluffychat/pangea/models/speech_to_text_models.dart'; @@ -663,161 +658,26 @@ class PangeaMessageEvent { l2Code == null ? [] : practiceActivitiesByLangCode(l2Code!); /// all construct uses for the message, including vocab and grammar - List get allConstructUses => - [..._grammarConstructUses, ..._vocabUses, ..._itStepsToConstructUses]; - - /// Returns a list of [OneConstructUse] from itSteps for which the continuance - /// was selected or ignored. Correct selections are considered in the tokens - /// flow. Once all continuances have lemmas, we can do both correct and incorrect - /// in this flow. It actually doesn't do anything at all right now, because the - /// choregrapher is not returning lemmas for continuances. This is a TODO. - /// So currently only the lemmas can be gotten from the tokens for choices that - /// are actually in the final message. - List get _itStepsToConstructUses { - final List uses = []; - if (originalSent?.choreo == null) return uses; - - for (final itStep in originalSent!.choreo!.itSteps) { - for (final continuance in itStep.continuances) { - final List tokensToSave = - continuance.tokens.where((t) => t.lemma.saveVocab).toList(); - - if (originalSent!.choreo!.finalMessage.contains(continuance.text)) { - continue; - } - if (continuance.wasClicked) { - //PTODO - account for end of flow score - if (continuance.level != ChoreoConstants.levelThresholdForGreen) { - for (final token in tokensToSave) { - uses.add( - _lemmaToVocabUse( - token.lemma, - ConstructUseTypeEnum.incIt, - ), - ); - } - } - } else { - if (continuance.level != ChoreoConstants.levelThresholdForGreen) { - for (final token in tokensToSave) { - uses.add( - _lemmaToVocabUse( - token.lemma, - ConstructUseTypeEnum.ignIt, - ), - ); - } - } - } - } - } - return uses; - } + List get allConstructUses => [ + ..._grammarConstructUses, + ..._vocabUses, + ]; /// get construct uses of type vocab for the message List get _vocabUses { - final List uses = []; - - // missing vital info so return - if (event.roomId == null || originalSent?.tokens == null) { - // debugger(when: kDebugMode); - return uses; - } - - // for each token, record whether selected in ga, ta, or wa - for (final token in originalSent!.tokens! - .where((token) => token.lemma.saveVocab) - .toList()) { - uses.add(_getVocabUseForToken(token)); - } - - return uses; - } - - /// Returns a [OneConstructUse] for the given [token] - /// If there is no [originalSent] or [originalSent.choreo], the [token] is - /// considered to be a [ConstructUseTypeEnum.wa] as long as it matches the target language. - /// Later on, we may want to consider putting it in some category of like 'pending' - /// If the [token] is in the [originalSent.choreo.acceptedOrIgnoredMatch], - /// it is considered to be a [ConstructUseTypeEnum.ga]. - /// If the [token] is in the [originalSent.choreo.acceptedOrIgnoredMatch.choices], - /// it is considered to be a [ConstructUseTypeEnum.corIt]. - /// If the [token] is not included in any choreoStep, it is considered to be a [ConstructUseTypeEnum.wa]. - OneConstructUse _getVocabUseForToken(PangeaToken token) { - if (originalSent?.choreo == null) { - final bool inUserL2 = originalSent?.langCode == l2Code; - return _lemmaToVocabUse( - token.lemma, - inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk, + if (originalSent?.tokens != null) { + return originalSent!.content.vocabUses( + event: event, + choreo: originalSent!.choreo, + tokens: originalSent!.tokens!, ); } - - for (final step in originalSent!.choreo!.choreoSteps) { - /// if 1) accepted match 2) token is in the replacement and 3) replacement - /// is in the overall step text, then token was a ga - if (step.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.accepted && - (step.acceptedOrIgnoredMatch!.match.choices?.any( - (r) => - r.value.contains(token.text.content) && - step.text.contains(r.value), - ) ?? - false)) { - return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.ga); - } - if (step.itStep != null) { - final bool pickedThroughIT = - step.itStep!.chosenContinuance?.text.contains(token.text.content) ?? - false; - if (pickedThroughIT) { - return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.corIt); - //PTODO - check if added via custom input in IT flow - } - } - } - return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.wa); + return []; } - OneConstructUse _lemmaToVocabUse( - Lemma lemma, - ConstructUseTypeEnum type, - ) => - OneConstructUse( - useType: type, - chatId: event.roomId!, - timeStamp: event.originServerTs, - lemma: lemma.text, - form: lemma.form, - msgId: event.eventId, - constructType: ConstructTypeEnum.vocab, - ); - /// get construct uses of type grammar for the message - List get _grammarConstructUses { - final List uses = []; - - if (originalSent?.choreo == null || event.roomId == null) return uses; - - for (final step in originalSent!.choreo!.choreoSteps) { - if (step.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.accepted) { - final String name = step.acceptedOrIgnoredMatch!.match.rule?.id ?? - step.acceptedOrIgnoredMatch!.match.shortMessage ?? - step.acceptedOrIgnoredMatch!.match.type.typeName.name; - uses.add( - OneConstructUse( - useType: ConstructUseTypeEnum.ga, - chatId: event.roomId!, - timeStamp: event.originServerTs, - lemma: name, - form: name, - msgId: event.eventId, - constructType: ConstructTypeEnum.grammar, - id: "${event.eventId}_${step.acceptedOrIgnoredMatch!.match.offset}_${step.acceptedOrIgnoredMatch!.match.length}", - ), - ); - } - } - return uses; - } + List get _grammarConstructUses => + originalSent?.choreo?.grammarConstructUses(event: event) ?? []; } class URLFinder { diff --git a/lib/pangea/matrix_event_wrappers/practice_activity_record_event.dart b/lib/pangea/matrix_event_wrappers/practice_activity_record_event.dart index 77b4948fd..8378d9f88 100644 --- a/lib/pangea/matrix_event_wrappers/practice_activity_record_event.dart +++ b/lib/pangea/matrix_event_wrappers/practice_activity_record_event.dart @@ -1,12 +1,5 @@ -import 'dart:developer'; - import 'package:fluffychat/pangea/extensions/pangea_event_extension.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; -import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; -import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; import '../constants/pangea_event_types.dart'; @@ -28,62 +21,4 @@ class PracticeActivityRecordEvent { _content ??= event.getPangeaContent(); return _content!; } - - Future> uses(Timeline timeline) async { - try { - final String? parent = event.relationshipEventId; - if (parent == null) { - debugger(when: kDebugMode); - ErrorHandler.logError( - m: "PracticeActivityRecordEvent has null event.relationshipEventId", - data: event.toJson(), - ); - return []; - } - - final Event? practiceEvent = - await timeline.getEventById(event.relationshipEventId!); - - if (practiceEvent == null) { - debugger(when: kDebugMode); - ErrorHandler.logError( - m: "PracticeActivityRecordEvent has null practiceActivityEvent with id $parent", - data: event.toJson(), - ); - return []; - } - - final PracticeActivityEvent practiceActivity = PracticeActivityEvent( - event: practiceEvent, - timeline: timeline, - ); - - final List uses = []; - - final List constructIds = - practiceActivity.practiceActivity.tgtConstructs; - - for (final construct in constructIds) { - uses.add( - OneConstructUse( - lemma: construct.lemma, - constructType: construct.type, - useType: record.useType, - //TODO - find form of construct within the message - //this is related to the feature of highlighting the target construct in the message - form: construct.lemma, - chatId: event.roomId ?? practiceEvent.roomId ?? timeline.room.id, - msgId: practiceActivity.parentMessageId, - timeStamp: event.originServerTs, - ), - ); - } - - return uses; - } catch (e, s) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: e, s: s, data: event.toJson()); - rethrow; - } - } } diff --git a/lib/pangea/models/analytics/analytics_event.dart b/lib/pangea/models/analytics/analytics_event.dart deleted file mode 100644 index 7010d3591..000000000 --- a/lib/pangea/models/analytics/analytics_event.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; -import 'package:fluffychat/pangea/models/analytics/analytics_model.dart'; -import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; -import 'package:fluffychat/pangea/models/analytics/summary_analytics_model.dart'; -import 'package:matrix/matrix.dart'; - -// superclass for all analytics events -abstract class AnalyticsEvent { - late Event _event; - AnalyticsModel? contentCache; - - AnalyticsEvent({required Event event}) { - _event = event; - } - - Event get event => _event; - - AnalyticsModel get content { - switch (_event.type) { - case PangeaEventTypes.summaryAnalytics: - contentCache ??= SummaryAnalyticsModel.fromJson(event.content); - break; - case PangeaEventTypes.construct: - contentCache ??= ConstructAnalyticsModel.fromJson(event.content); - break; - } - return contentCache!; - } -} diff --git a/lib/pangea/models/analytics/analytics_model.dart b/lib/pangea/models/analytics/analytics_model.dart deleted file mode 100644 index d8732ad97..000000000 --- a/lib/pangea/models/analytics/analytics_model.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; -import 'package:fluffychat/pangea/models/analytics/summary_analytics_model.dart'; - -abstract class AnalyticsModel { - static List formatAnalyticsContent( - List recentMsgs, - String type, - ) { - switch (type) { - case PangeaEventTypes.summaryAnalytics: - return SummaryAnalyticsModel.formatSummaryContent(recentMsgs); - case PangeaEventTypes.construct: - final List uses = []; - for (final msg in recentMsgs) { - uses.addAll(msg.allConstructUses); - } - return uses; - } - return []; - } -} diff --git a/lib/pangea/models/analytics/chart_analytics_model.dart b/lib/pangea/models/analytics/chart_analytics_model.dart index 7430ede2f..4a9f278be 100644 --- a/lib/pangea/models/analytics/chart_analytics_model.dart +++ b/lib/pangea/models/analytics/chart_analytics_model.dart @@ -1,149 +1,149 @@ -import 'dart:developer'; +// import 'dart:developer'; -import 'package:fluffychat/pangea/enum/time_span.dart'; -import 'package:fluffychat/pangea/models/analytics/summary_analytics_model.dart'; -import 'package:flutter/foundation.dart'; +// import 'package:fluffychat/pangea/enum/time_span.dart'; +// import 'package:fluffychat/pangea/models/analytics/summary_analytics_model.dart'; +// import 'package:flutter/foundation.dart'; -import '../../enum/use_type.dart'; +// import '../../enum/use_type.dart'; -class TimeSeriesTotals { - int ta; - int ga; - int wa; - int un; +// class TimeSeriesTotals { +// int ta; +// int ga; +// int wa; +// int un; - int get all => ta + ga + wa + un; +// int get all => ta + ga + wa + un; - TimeSeriesTotals({ - required this.ta, - required this.ga, - required this.wa, - required this.un, - }); +// TimeSeriesTotals({ +// required this.ta, +// required this.ga, +// required this.wa, +// required this.un, +// }); - Map toJson() => { - UseType.ta.string: ta, - UseType.ga.string: ga, - UseType.wa.string: wa, - UseType.un.string: un, - }; +// Map toJson() => { +// UseType.ta.string: ta, +// UseType.ga.string: ga, +// UseType.wa.string: wa, +// UseType.un.string: un, +// }; - factory TimeSeriesTotals.fromJson(json) => TimeSeriesTotals( - ta: json[UseType.ta.string], - ga: json[UseType.ga.string], - wa: json[UseType.wa.string], - un: json[UseType.un.string], - ); +// factory TimeSeriesTotals.fromJson(json) => TimeSeriesTotals( +// ta: json[UseType.ta.string], +// ga: json[UseType.ga.string], +// wa: json[UseType.wa.string], +// un: json[UseType.un.string], +// ); - static get empty => TimeSeriesTotals(ta: 0, ga: 0, wa: 0, un: 0); +// static get empty => TimeSeriesTotals(ta: 0, ga: 0, wa: 0, un: 0); - int get taPercent => all != 0 ? (ta / all * 100).round() : 0; - int get gaPercent => all != 0 ? (ga / all * 100).round() : 0; - int get waPercent => all != 0 ? (wa / all * 100).round() : 0; - int get unPercent => all != 0 ? (un / all * 100).round() : 0; +// int get taPercent => all != 0 ? (ta / all * 100).round() : 0; +// int get gaPercent => all != 0 ? (ga / all * 100).round() : 0; +// int get waPercent => all != 0 ? (wa / all * 100).round() : 0; +// int get unPercent => all != 0 ? (un / all * 100).round() : 0; - void increment(RecentMessageRecord msg) { - switch (msg.useType) { - case UseType.ta: - ta += 1; - break; - case UseType.wa: - wa += 1; - break; - case UseType.ga: - ga += 1; - break; - case UseType.un: - un += 1; - break; - default: - debugger(when: kDebugMode); - debugPrint("message with bad type ${msg.toJson()}"); - } - } -} +// void increment(RecentMessageRecord msg) { +// switch (msg.useType) { +// case UseType.ta: +// ta += 1; +// break; +// case UseType.wa: +// wa += 1; +// break; +// case UseType.ga: +// ga += 1; +// break; +// case UseType.un: +// un += 1; +// break; +// default: +// debugger(when: kDebugMode); +// debugPrint("message with bad type ${msg.toJson()}"); +// } +// } +// } -class TimeSeriesInterval { - DateTime start; - DateTime end; - TimeSeriesTotals totals; +// class TimeSeriesInterval { +// DateTime start; +// DateTime end; +// TimeSeriesTotals totals; - TimeSeriesInterval({ - required this.start, - required this.end, - required this.totals, - }); +// TimeSeriesInterval({ +// required this.start, +// required this.end, +// required this.totals, +// }); - Map toJson() => { - "strt": start.toIso8601String(), - "end": end.toIso8601String(), - "totals": totals.toJson(), - }; +// Map toJson() => { +// "strt": start.toIso8601String(), +// "end": end.toIso8601String(), +// "totals": totals.toJson(), +// }; - factory TimeSeriesInterval.fromJson(json) => TimeSeriesInterval( - start: DateTime.parse(json["strt"]), - end: DateTime.parse(json["end"]), - totals: TimeSeriesTotals.fromJson(json["totals"]), - ); -} +// factory TimeSeriesInterval.fromJson(json) => TimeSeriesInterval( +// start: DateTime.parse(json["strt"]), +// end: DateTime.parse(json["end"]), +// totals: TimeSeriesTotals.fromJson(json["totals"]), +// ); +// } -class ChartAnalyticsModel { - final TimeSpan timeSpan; - final TimeSeriesTotals totals = TimeSeriesTotals.empty; - final List msgs; - final String? chatId; +// class ChartAnalyticsModel { +// final TimeSpan timeSpan; +// final TimeSeriesTotals totals = TimeSeriesTotals.empty; +// final List msgs; +// final String? chatId; - late DateTime fetchedAt; - late List timeSeries; - DateTime? lastMessage; +// late DateTime fetchedAt; +// late List timeSeries; +// DateTime? lastMessage; - ChartAnalyticsModel({ - required this.timeSpan, - required this.msgs, - this.chatId, - }) { - fetchedAt = DateTime.now(); - calculate(); - } +// ChartAnalyticsModel({ +// required this.timeSpan, +// required this.msgs, +// this.chatId, +// }) { +// fetchedAt = DateTime.now(); +// calculate(); +// } - bool get isEmpty => (totals.ga + totals.ta + totals.wa == 0); +// bool get isEmpty => (totals.ga + totals.ta + totals.wa == 0); - void calculate() { - final Map intervals = timeSpan.emptyIntervals; - final DateTime cutOff = timeSpan.cutOffDate; +// void calculate() { +// final Map intervals = timeSpan.emptyIntervals; +// final DateTime cutOff = timeSpan.cutOffDate; - final filtered = msgs.where( - (msg) => - (chatId == null || msg.chatId == chatId) && msg.time.isAfter(cutOff), - ); +// final filtered = msgs.where( +// (msg) => +// (chatId == null || msg.chatId == chatId) && msg.time.isAfter(cutOff), +// ); - //remove msgs with duplicate ids - final Map unique = {}; - for (final msg in filtered) { - if (unique[msg.eventId] == null) { - unique[msg.eventId] = msg; - } - } +// //remove msgs with duplicate ids +// final Map unique = {}; +// for (final msg in filtered) { +// if (unique[msg.eventId] == null) { +// unique[msg.eventId] = msg; +// } +// } - for (final msg in unique.values) { - final String key = timeSpan.getMapKey(msg.time); - if (intervals[key] == null) { - debugger(when: kDebugMode); - } else { - intervals[key]!.totals.increment(msg); - totals.increment(msg); - lastMessage = msg.time; - } - } - timeSeries = intervals.values.toList().reversed.toList(); - } +// for (final msg in unique.values) { +// final String key = timeSpan.getMapKey(msg.time); +// if (intervals[key] == null) { +// debugger(when: kDebugMode); +// } else { +// intervals[key]!.totals.increment(msg); +// totals.increment(msg); +// lastMessage = msg.time; +// } +// } +// timeSeries = intervals.values.toList().reversed.toList(); +// } - DateTime? get lastMessageTime { - if (msgs.isEmpty) { - return null; - } - return msgs.map((msg) => msg.time).reduce( - (compare, recent) => compare.isAfter(recent) ? compare : recent, - ); - } -} +// DateTime? get lastMessageTime { +// if (msgs.isEmpty) { +// return null; +// } +// return msgs.map((msg) => msg.time).reduce( +// (compare, recent) => compare.isAfter(recent) ? compare : recent, +// ); +// } +// } diff --git a/lib/pangea/models/analytics/construct_list_model.dart b/lib/pangea/models/analytics/construct_list_model.dart new file mode 100644 index 000000000..661fa9d0b --- /dev/null +++ b/lib/pangea/models/analytics/construct_list_model.dart @@ -0,0 +1,144 @@ +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; + +/// A wrapper around a list of [OneConstructUse]s, used to simplify +/// the process of filtering / sorting / displaying the events. +/// Takes a construct type and a list of events +class ConstructListModel { + final ConstructTypeEnum type; + final List _uses; + + ConstructListModel({ + required this.type, + uses, + }) : _uses = uses ?? []; + + List? _constructs; + List? _typedConstructs; + + List get uses => + _uses.where((use) => use.constructType == type).toList(); + + /// All unique lemmas used in the construct events + List get lemmas => constructs.map((e) => e.lemma).toSet().toList(); + + /// A list of ConstructUses, each of which contains a lemma and + /// a list of uses, sorted by the number of uses + List get constructs { + // the list of uses doesn't change so we don't have to re-calculate this + if (_constructs != null) return _constructs!; + final Map> lemmaToUses = {}; + for (final use in uses) { + if (use.lemma == null) continue; + lemmaToUses[use.lemma!] ??= []; + lemmaToUses[use.lemma!]!.add(use); + } + + final constructUses = lemmaToUses.entries + .map( + (entry) => ConstructUses( + lemma: entry.key, + uses: entry.value, + constructType: type, + ), + ) + .toList(); + + constructUses.sort((a, b) { + final comp = b.uses.length.compareTo(a.uses.length); + if (comp != 0) return comp; + return a.lemma.compareTo(b.lemma); + }); + + _constructs = constructUses; + return constructUses; + } + + /// A list of ConstructUseTypeUses, each of which + /// contains a lemma, a use type, and a list of uses + List get typedConstructs { + if (_typedConstructs != null) return _typedConstructs!; + final List typedConstructs = []; + for (final construct in constructs) { + final typeToUses = >{}; + for (final use in construct.uses) { + typeToUses[use.useType] ??= []; + typeToUses[use.useType]!.add(use); + } + for (final typeEntry in typeToUses.entries) { + typedConstructs.add( + ConstructUseTypeUses( + lemma: construct.lemma, + constructType: type, + useType: typeEntry.key, + uses: typeEntry.value, + ), + ); + } + } + return typedConstructs; + } + + /// The total number of points for all uses of this construct type + int get points { + // double totalPoints = 0; + return typedConstructs.fold( + 0, + (total, typedConstruct) => + total + + typedConstruct.useType.pointValue * typedConstruct.uses.length, + ); + // Commenting this out for now + // Minimize the amount of points given for repeated uses of the same lemma. + // i.e., if a lemma is used 4 times without assistance, the point value for + // a use without assistance is 3. So the points would be + // 3/1 + 3/2 + 3/3 + 3/4 = 3 + 1.5 + 1 + 0.75 = 5.25 (instead of 12) + // for (final typedConstruct in typedConstructs) { + // final pointValue = typedConstruct.useType.pointValue; + // double calc = 0.0; + // for (int k = 1; k <= typedConstruct.uses.length; k++) { + // calc += pointValue / k; + // } + // totalPoints += calc; + // } + // return totalPoints.round(); + } +} + +/// One lemma and a list of construct uses for that lemma +class ConstructUses { + final List uses; + final ConstructTypeEnum constructType; + final String lemma; + + ConstructUses({ + required this.uses, + required this.constructType, + required this.lemma, + }); + + // Total points for all uses of this lemma + int get points { + return uses.fold( + 0, + (total, use) => total + use.useType.pointValue, + ); + } +} + +/// One lemma, a use type, and a list of uses +/// for that lemma and use type +class ConstructUseTypeUses { + final ConstructUseTypeEnum useType; + final ConstructTypeEnum constructType; + final String lemma; + final List uses; + + ConstructUseTypeUses({ + required this.useType, + required this.constructType, + required this.lemma, + required this.uses, + }); +} diff --git a/lib/pangea/models/analytics/constructs_event.dart b/lib/pangea/models/analytics/constructs_event.dart index 481051b1c..89336bbbc 100644 --- a/lib/pangea/models/analytics/constructs_event.dart +++ b/lib/pangea/models/analytics/constructs_event.dart @@ -1,11 +1,13 @@ -import 'package:fluffychat/pangea/models/analytics/analytics_event.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:matrix/matrix.dart'; import '../../constants/pangea_event_types.dart'; -class ConstructAnalyticsEvent extends AnalyticsEvent { - ConstructAnalyticsEvent({required Event event}) : super(event: event) { +class ConstructAnalyticsEvent { + late Event _event; + ConstructAnalyticsModel? contentCache; + ConstructAnalyticsEvent({required Event event}) { + _event = event; if (event.type != PangeaEventTypes.construct) { throw Exception( "${event.type} should not be used to make a ConstructAnalyticsEvent", @@ -13,7 +15,8 @@ class ConstructAnalyticsEvent extends AnalyticsEvent { } } - @override + Event get event => _event; + ConstructAnalyticsModel get content { contentCache ??= ConstructAnalyticsModel.fromJson(event.content); return contentCache as ConstructAnalyticsModel; diff --git a/lib/pangea/models/analytics/constructs_model.dart b/lib/pangea/models/analytics/constructs_model.dart index 54e81789f..fd9710a80 100644 --- a/lib/pangea/models/analytics/constructs_model.dart +++ b/lib/pangea/models/analytics/constructs_model.dart @@ -1,14 +1,14 @@ import 'dart:developer'; +import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; -import 'package:fluffychat/pangea/models/analytics/analytics_model.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:matrix/matrix.dart'; import '../../enum/construct_type_enum.dart'; -class ConstructAnalyticsModel extends AnalyticsModel { +class ConstructAnalyticsModel { List uses; ConstructAnalyticsModel({ @@ -38,12 +38,14 @@ class ConstructAnalyticsModel extends AnalyticsModel { for (final useData in lemmaUses) { final use = OneConstructUse( useType: ConstructUseTypeEnum.ga, - chatId: useData["chatId"], - timeStamp: DateTime.parse(useData["timeStamp"]), lemma: lemma, form: useData["form"], - msgId: useData["msgId"], constructType: ConstructTypeEnum.grammar, + metadata: ConstructUseMetaData( + eventId: useData["msgId"], + roomId: useData["chatId"], + timeStamp: DateTime.parse(useData["timeStamp"]), + ), ); uses.add(use); } @@ -72,77 +74,87 @@ class ConstructAnalyticsModel extends AnalyticsModel { class OneConstructUse { String? lemma; - ConstructTypeEnum? constructType; String? form; + List categories; + ConstructTypeEnum? constructType; ConstructUseTypeEnum useType; - String chatId; - String? msgId; - DateTime timeStamp; String? id; + ConstructUseMetaData metadata; OneConstructUse({ required this.useType, - required this.chatId, - required this.timeStamp, required this.lemma, - required this.form, - required this.msgId, required this.constructType, + required this.metadata, + this.categories = const [], + this.form, this.id, }); + String get chatId => metadata.roomId; + String get msgId => metadata.eventId!; + DateTime get timeStamp => metadata.timeStamp; + factory OneConstructUse.fromJson(Map json) { return OneConstructUse( useType: ConstructUseTypeEnum.values - .firstWhere((e) => e.string == json['useType']), - chatId: json['chatId'], - timeStamp: DateTime.parse(json['timeStamp']), + .firstWhereOrNull((e) => e.string == json['useType']) ?? + ConstructUseTypeEnum.unk, lemma: json['lemma'], form: json['form'], - msgId: json['msgId'], + categories: json['categories'] != null + ? List.from(json['categories']) + : [], constructType: json['constructType'] != null ? ConstructTypeUtil.fromString(json['constructType']) : null, id: json['id'], + metadata: ConstructUseMetaData( + eventId: json['msgId'], + roomId: json['chatId'], + timeStamp: DateTime.parse(json['timeStamp']), + ), ); } Map toJson([bool condensed = false]) { - final Map data = { + final Map data = { 'useType': useType.string, - 'chatId': chatId, - 'timeStamp': timeStamp.toIso8601String(), + 'chatId': metadata.roomId, + 'timeStamp': metadata.timeStamp.toIso8601String(), 'form': form, - 'msgId': msgId, + 'msgId': metadata.eventId, }; if (!condensed && lemma != null) data['lemma'] = lemma!; if (!condensed && constructType != null) { data['constructType'] = constructType!.string; } if (id != null) data['id'] = id; - + data['categories'] = categories; return data; } Room? getRoom(Client client) { - return client.getRoomById(chatId); + return client.getRoomById(metadata.roomId); } Future getEvent(Client client) async { final Room? room = getRoom(client); - if (room == null || msgId == null) return null; - return room.getEventById(msgId!); + if (room == null || metadata.eventId == null) return null; + return room.getEventById(metadata.eventId!); } + + int get pointValue => useType.pointValue; } -class ConstructUses { - final List uses; - final ConstructTypeEnum constructType; - final String lemma; +class ConstructUseMetaData { + String? eventId; + String roomId; + DateTime timeStamp; - ConstructUses({ - required this.uses, - required this.constructType, - required this.lemma, + ConstructUseMetaData({ + required this.roomId, + required this.timeStamp, + this.eventId, }); } diff --git a/lib/pangea/models/analytics/summary_analytics_event.dart b/lib/pangea/models/analytics/summary_analytics_event.dart deleted file mode 100644 index a764d5597..000000000 --- a/lib/pangea/models/analytics/summary_analytics_event.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:fluffychat/pangea/models/analytics/analytics_event.dart'; -import 'package:fluffychat/pangea/models/analytics/summary_analytics_model.dart'; -import 'package:matrix/matrix.dart'; - -import '../../constants/pangea_event_types.dart'; - -class SummaryAnalyticsEvent extends AnalyticsEvent { - SummaryAnalyticsEvent({required Event event}) : super(event: event) { - if (event.type != PangeaEventTypes.summaryAnalytics) { - throw Exception( - "${event.type} should not be used to make a SummaryAnalyticsEvent", - ); - } - } - - @override - SummaryAnalyticsModel get content { - contentCache ??= SummaryAnalyticsModel.fromJson(event.content); - return contentCache as SummaryAnalyticsModel; - } -} diff --git a/lib/pangea/models/analytics/summary_analytics_model.dart b/lib/pangea/models/analytics/summary_analytics_model.dart deleted file mode 100644 index 0b8e4b27c..000000000 --- a/lib/pangea/models/analytics/summary_analytics_model.dart +++ /dev/null @@ -1,111 +0,0 @@ -import 'dart:convert'; - -import 'package:fluffychat/pangea/enum/use_type.dart'; -import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; -import 'package:fluffychat/pangea/models/analytics/analytics_model.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:flutter/foundation.dart'; - -class SummaryAnalyticsModel extends AnalyticsModel { - late List _messages; - - SummaryAnalyticsModel({ - required List messages, - }) { - _messages = messages; - } - - List get messages => _messages; - - static const _messagesKey = "msgs"; - - Map toJson() => { - _messagesKey: jsonEncode(_messages.map((e) => e.toJson()).toList()), - }; - - factory SummaryAnalyticsModel.fromJson(json) { - List savedMessages = []; - try { - savedMessages = json[_messagesKey] != null - ? (jsonDecode(json[_messagesKey] ?? "[]") as Iterable) - .map((e) => RecentMessageRecord.fromJson(e)) - .toList() - .cast() - : []; - } catch (err, stack) { - if (kDebugMode) rethrow; - ErrorHandler.logError(e: err, s: stack); - } - return SummaryAnalyticsModel( - messages: savedMessages, - ); - } - - static List formatSummaryContent( - List recentMsgs, - ) { - final List filtered = List.from(recentMsgs); - final List records = filtered - .map( - (msg) => RecentMessageRecord( - eventId: msg.eventId, - chatId: msg.room.id, - useType: msg.msgUseType, - time: msg.originServerTs, - ), - ) - .toList(); - - return records; - } -} - -class RecentMessageRecord { - String eventId; - String chatId; - UseType useType; - DateTime time; - - RecentMessageRecord({ - required this.eventId, - required this.chatId, - required this.useType, - required this.time, - }); - - factory RecentMessageRecord.fromJson(Map json) => - RecentMessageRecord( - eventId: json[_eventIdKey], - chatId: json[_chatIdKey], - useType: _typeStringToEnum(json[_typeOfUseKey]), - time: DateTime.parse(json[_timeKey]), - ); - - Map toJson() => { - _eventIdKey: eventId, - _chatIdKey: chatId, - _typeOfUseKey: _typeEnumToString(useType), - _timeKey: time.toIso8601String(), - }; - - String _typeEnumToString(dynamic status) => status.toString().split('.').last; - - static UseType _typeStringToEnum(String useType) { - final String lastPart = useType.toString().split('.').last; - switch (lastPart) { - case 'ta': - return UseType.ta; - case 'ga': - return UseType.ga; - case 'wa': - return UseType.wa; - default: - return UseType.un; - } - } - - static const _eventIdKey = "m.id"; - static const _chatIdKey = "c.id"; - static const _typeOfUseKey = "typ"; - static const _timeKey = "t"; -} diff --git a/lib/pangea/models/choreo_record.dart b/lib/pangea/models/choreo_record.dart index 3586fcee1..fe95dfc09 100644 --- a/lib/pangea/models/choreo_record.dart +++ b/lib/pangea/models/choreo_record.dart @@ -1,6 +1,10 @@ import 'dart:convert'; +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; +import 'package:matrix/matrix.dart'; import 'it_step.dart'; @@ -111,6 +115,44 @@ class ChoreoRecord { String get finalMessage => choreoSteps.isNotEmpty ? choreoSteps.last.text : ""; + + /// Get construct uses of type grammar for the message from this ChoreoRecord. + /// Takes either an event (typically when the Representation itself is + /// available) or construct use metadata (when the event is not available, + /// i.e. immediately after message send) to create the construct uses. + List grammarConstructUses({ + Event? event, + ConstructUseMetaData? metadata, + }) { + final List uses = []; + if (event?.roomId == null && metadata?.roomId == null) { + return uses; + } + metadata ??= ConstructUseMetaData( + roomId: event!.roomId!, + eventId: event.eventId, + timeStamp: event.originServerTs, + ); + + for (final step in choreoSteps) { + if (step.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.accepted) { + final String name = step.acceptedOrIgnoredMatch!.match.rule?.id ?? + step.acceptedOrIgnoredMatch!.match.shortMessage ?? + step.acceptedOrIgnoredMatch!.match.type.typeName.name; + uses.add( + OneConstructUse( + useType: ConstructUseTypeEnum.ga, + lemma: name, + form: name, + constructType: ConstructTypeEnum.grammar, + id: "${metadata.eventId}_${step.acceptedOrIgnoredMatch!.match.offset}_${step.acceptedOrIgnoredMatch!.match.length}", + metadata: metadata, + ), + ); + } + } + return uses; + } } /// A new ChoreoRecordStep is saved in the following cases: diff --git a/lib/pangea/models/igc_text_data_model.dart b/lib/pangea/models/igc_text_data_model.dart index 5f32f92d1..014b39524 100644 --- a/lib/pangea/models/igc_text_data_model.dart +++ b/lib/pangea/models/igc_text_data_model.dart @@ -227,37 +227,6 @@ class IGCTextData { decorationThickness: 5, ); - List getMatchTokens() { - final List matchTokens = []; - int? endTokenIndex; - PangeaMatch? topMatch; - for (final (i, token) in tokens.indexed) { - if (endTokenIndex != null) { - if (i <= endTokenIndex) { - matchTokens.add( - MatchToken( - token: token, - match: topMatch, - ), - ); - continue; - } - endTokenIndex = null; - } - topMatch = getTopMatchForToken(token); - if (topMatch != null) { - endTokenIndex = tokens.indexWhere((e) => e.end >= topMatch!.end, i); - } - matchTokens.add( - MatchToken( - token: token, - match: topMatch, - ), - ); - } - return matchTokens; - } - TextSpan getSpanItem({ required int start, required int end, @@ -347,11 +316,19 @@ class IGCTextData { return items; } -} -class MatchToken { - final PangeaToken token; - final PangeaMatch? match; + List matchTokens(int matchIndex) { + if (matchIndex >= matches.length) { + return []; + } - MatchToken({required this.token, this.match}); + final PangeaMatch match = matches[matchIndex]; + final List tokensForMatch = []; + for (final token in tokens) { + if (match.isOffsetInMatchSpan(token.text.offset)) { + tokensForMatch.add(token); + } + } + return tokensForMatch; + } } diff --git a/lib/pangea/models/lemma.dart b/lib/pangea/models/lemma.dart index 1dc44c4b5..f297d60b0 100644 --- a/lib/pangea/models/lemma.dart +++ b/lib/pangea/models/lemma.dart @@ -1,3 +1,7 @@ +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; + /// Represents a lemma object class Lemma { /// [text] ex "ir" - text of the lemma of the word @@ -35,4 +39,18 @@ class Lemma { static Lemma create(String form) => Lemma(text: '', saveVocab: true, form: form); + + /// Given a [type] and [metadata], returns a [OneConstructUse] for this lemma + OneConstructUse toVocabUse( + ConstructUseTypeEnum type, + ConstructUseMetaData metadata, + ) { + return OneConstructUse( + useType: type, + lemma: text, + form: form, + constructType: ConstructTypeEnum.vocab, + metadata: metadata, + ); + } } diff --git a/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart b/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart index 0c4ea52bf..34f73e735 100644 --- a/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart +++ b/lib/pangea/models/practice_activities.dart/practice_activity_record_model.dart @@ -3,9 +3,14 @@ // the user might have selected multiple options before // finding the answer import 'dart:developer'; -import 'dart:typed_data'; import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; +import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart'; +import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:flutter/foundation.dart'; +import 'package:matrix/matrix.dart'; class PracticeActivityRecordModel { final String? question; @@ -79,6 +84,56 @@ class PracticeActivityRecordModel { } } + /// Returns a list of [OneConstructUse] objects representing the uses of the practice activity. + /// + /// The [practiceActivity] parameter is the parent event, representing the activity itself. + /// The [event] parameter is the record event, if available. + /// The [metadata] parameter is the metadata for the construct use, used if the record event isn't available. + /// + /// If [event] and [metadata] are both null, an empty list is returned. + /// + /// The method iterates over the [tgtConstructs] of the [practiceActivity] and creates a [OneConstructUse] object for each construct. + List uses( + PracticeActivityEvent practiceActivity, { + Event? event, + ConstructUseMetaData? metadata, + }) { + try { + if (event == null && metadata == null) { + debugger(when: kDebugMode); + return []; + } + + final List uses = []; + final List constructIds = + practiceActivity.practiceActivity.tgtConstructs; + + for (final construct in constructIds) { + uses.add( + OneConstructUse( + lemma: construct.lemma, + constructType: construct.type, + useType: useType, + //TODO - find form of construct within the message + //this is related to the feature of highlighting the target construct in the message + form: construct.lemma, + metadata: ConstructUseMetaData( + roomId: event?.roomId ?? metadata!.roomId, + eventId: practiceActivity.parentMessageId, + timeStamp: event?.originServerTs ?? metadata!.timeStamp, + ), + ), + ); + } + + return uses; + } catch (e, s) { + debugger(when: kDebugMode); + ErrorHandler.logError(e: e, s: s, data: event?.toJson()); + rethrow; + } + } + @override bool operator ==(Object other) { if (identical(this, other)) return true; diff --git a/lib/pangea/models/representation_content_model.dart b/lib/pangea/models/representation_content_model.dart index f49a465b4..9fb96f1e9 100644 --- a/lib/pangea/models/representation_content_model.dart +++ b/lib/pangea/models/representation_content_model.dart @@ -1,4 +1,11 @@ +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; +import 'package:fluffychat/pangea/models/choreo_record.dart'; +import 'package:fluffychat/pangea/models/pangea_match_model.dart'; +import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/speech_to_text_models.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import 'package:matrix/matrix.dart'; /// this class is contained within a [RepresentationEvent] @@ -81,4 +88,145 @@ class PangeaRepresentation { } return data; } + + /// Get construct uses of type vocab for the message. + /// Takes a list of tokens and a choreo record, which is searched + /// through for each token for its construct use type. + /// Also takes either an event (typically when the Representation itself is + /// available) or construct use metadata (when the event is not available, + /// i.e. immediately after message send) to create the construct use. + List vocabUses({ + required List tokens, + Event? event, + ConstructUseMetaData? metadata, + ChoreoRecord? choreo, + }) { + final List uses = []; + + // missing vital info so return + if (event?.roomId == null && metadata?.roomId == null) { + // debugger(when: kDebugMode); + return uses; + } + + metadata ??= ConstructUseMetaData( + roomId: event!.roomId!, + eventId: event.eventId, + timeStamp: event.originServerTs, + ); + + // for each token, record whether selected in ga, ta, or wa + final tokensToSave = + tokens.where((token) => token.lemma.saveVocab).toList(); + for (final token in tokensToSave) { + uses.addAll( + getUsesForToken( + token, + metadata, + choreo: choreo, + ), + ); + } + + return uses; + } + + /// Returns a [OneConstructUse] for the given [token] + /// If there is no [choreo], the [token] is + /// considered to be a [ConstructUseTypeEnum.wa] as long as it matches the target language. + /// Later on, we may want to consider putting it in some category of like 'pending' + /// If the [token] is in the [choreo.acceptedOrIgnoredMatch], it is considered to be a [ConstructUseTypeEnum.ga]. + /// If the [token] is in the [choreo.acceptedOrIgnoredMatch.choices], it is considered to be a [ConstructUseTypeEnum.corIt]. + /// If the [token] is not included in any choreoStep, it is considered to be a [ConstructUseTypeEnum.wa]. + List getUsesForToken( + PangeaToken token, + ConstructUseMetaData metadata, { + ChoreoRecord? choreo, + }) { + final List uses = []; + final lemma = token.lemma; + final content = token.text.content; + + if (choreo == null) { + final bool inUserL2 = langCode == + MatrixState.pangeaController.languageController.activeL2Code(); + final useType = + inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk; + for (final entry in token.morph.entries) { + uses.add( + OneConstructUse( + useType: useType, + lemma: entry.value, + categories: [entry.key], + constructType: ConstructTypeEnum.morph, + metadata: metadata, + ), + ); + } + + if (lemma.saveVocab) { + uses.add( + lemma.toVocabUse( + inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk, + metadata, + ), + ); + } + return uses; + } + + for (final step in choreo.choreoSteps) { + /// if 1) accepted match 2) token is in the replacement and 3) replacement + /// is in the overall step text, then token was a ga + final bool isAcceptedMatch = + step.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.accepted; + final bool isITStep = step.itStep != null; + if (!isAcceptedMatch && !isITStep) continue; + + if (isAcceptedMatch && + step.acceptedOrIgnoredMatch?.match.choices != null) { + final choices = step.acceptedOrIgnoredMatch!.match.choices!; + final bool stepContainedToken = choices.any( + (choice) => + // if this choice contains the token's content + choice.value.contains(content) && + // if the complete input text after this step + // contains the choice (why is this here?) + step.text.contains(choice.value), + ); + if (stepContainedToken) { + return []; + } + } + + if (isITStep && step.itStep?.chosenContinuance != null) { + final bool pickedThroughIT = + step.itStep!.chosenContinuance!.text.contains(content); + if (pickedThroughIT) { + return []; + } + } + } + + for (final entry in token.morph.entries) { + uses.add( + OneConstructUse( + useType: ConstructUseTypeEnum.wa, + lemma: entry.value, + categories: [entry.key], + constructType: ConstructTypeEnum.morph, + metadata: metadata, + ), + ); + } + if (lemma.saveVocab) { + uses.add( + lemma.toVocabUse( + ConstructUseTypeEnum.wa, + metadata, + ), + ); + } + return uses; + } } diff --git a/lib/pangea/models/span_data.dart b/lib/pangea/models/span_data.dart index bf8ab8eca..8b7aaddac 100644 --- a/lib/pangea/models/span_data.dart +++ b/lib/pangea/models/span_data.dart @@ -5,6 +5,8 @@ // Call to server for additional/followup info import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/constants/model_keys.dart'; +import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:flutter/material.dart'; import '../enum/span_choice_type.dart'; @@ -99,14 +101,31 @@ class Context { } class SpanChoice { + String value; + SpanChoiceType type; + bool selected; + String? feedback; + DateTime? timestamp; + List tokens; + SpanChoice({ required this.value, required this.type, this.feedback, this.selected = false, this.timestamp, + this.tokens = const [], }); + factory SpanChoice.fromJson(Map json) { + final List tokensInternal = (json[ModelKey.tokens] != null) + ? (json[ModelKey.tokens] as Iterable) + .map( + (e) => PangeaToken.fromJson(e as Map), + ) + .toList() + .cast() + : []; return SpanChoice( value: json['value'] as String, type: json['type'] != null @@ -119,21 +138,17 @@ class SpanChoice { selected: json['selected'] ?? false, timestamp: json['timestamp'] != null ? DateTime.parse(json['timestamp']) : null, + tokens: tokensInternal, ); } - String value; - SpanChoiceType type; - bool selected; - String? feedback; - DateTime? timestamp; - Map toJson() => { 'value': value, 'type': type.name, 'selected': selected, 'feedback': feedback, 'timestamp': timestamp?.toIso8601String(), + 'tokens': tokens.map((e) => e.toJson()).toList(), }; String feedbackToDisplay(BuildContext context) { diff --git a/lib/pangea/pages/analytics/analytics_list_tile.dart b/lib/pangea/pages/analytics/analytics_list_tile.dart index a49ef4cb4..be55f32da 100644 --- a/lib/pangea/pages/analytics/analytics_list_tile.dart +++ b/lib/pangea/pages/analytics/analytics_list_tile.dart @@ -1,156 +1,157 @@ -import 'dart:async'; +// import 'dart:async'; -import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; -import 'package:matrix/matrix.dart'; -import '../../../../utils/date_time_extension.dart'; -import '../../../widgets/avatar.dart'; -import '../../../widgets/matrix.dart'; -import '../../models/analytics/chart_analytics_model.dart'; -import 'base_analytics.dart'; -import 'list_summary_analytics.dart'; +// import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; +// import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_gen/gen_l10n/l10n.dart'; +// import 'package:go_router/go_router.dart'; +// import 'package:matrix/matrix.dart'; -class AnalyticsListTile extends StatefulWidget { - const AnalyticsListTile({ - super.key, - required this.defaultSelected, - required this.selected, - required this.avatar, - required this.allowNavigateOnSelect, - required this.isSelected, - required this.onTap, - required this.pangeaController, - this.controller, - this.refreshStream, - }); +// import '../../../../utils/date_time_extension.dart'; +// import '../../../widgets/avatar.dart'; +// import '../../../widgets/matrix.dart'; +// import '../../models/analytics/chart_analytics_model.dart'; +// import 'base_analytics.dart'; +// import 'list_summary_analytics.dart'; - final void Function(AnalyticsSelected) onTap; +// class AnalyticsListTile extends StatefulWidget { +// const AnalyticsListTile({ +// super.key, +// required this.defaultSelected, +// required this.selected, +// required this.avatar, +// required this.allowNavigateOnSelect, +// required this.isSelected, +// required this.onTap, +// required this.pangeaController, +// this.controller, +// this.refreshStream, +// }); - final AnalyticsSelected defaultSelected; - final AnalyticsSelected selected; +// final void Function(AnalyticsSelected) onTap; - final Uri? avatar; +// final AnalyticsSelected defaultSelected; +// final AnalyticsSelected selected; - final bool allowNavigateOnSelect; - final bool isSelected; +// final Uri? avatar; - final PangeaController pangeaController; - final BaseAnalyticsController? controller; - final StreamController? refreshStream; +// final bool allowNavigateOnSelect; +// final bool isSelected; - @override - AnalyticsListTileState createState() => AnalyticsListTileState(); -} +// final PangeaController pangeaController; +// final BaseAnalyticsController? controller; +// final StreamController? refreshStream; -class AnalyticsListTileState extends State { - ChartAnalyticsModel? tileData; - StreamSubscription? refreshSubscription; +// @override +// AnalyticsListTileState createState() => AnalyticsListTileState(); +// } - @override - void initState() { - super.initState(); - setTileData(); - refreshSubscription = widget.refreshStream?.stream.listen((forceUpdate) { - setTileData(forceUpdate: forceUpdate); - }); - } +// class AnalyticsListTileState extends State { +// ChartAnalyticsModel? tileData; +// StreamSubscription? refreshSubscription; - @override - void didUpdateWidget(covariant AnalyticsListTile oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.selected != widget.selected) { - setTileData(); - } - } +// @override +// void initState() { +// super.initState(); +// setTileData(); +// refreshSubscription = widget.refreshStream?.stream.listen((forceUpdate) { +// setTileData(forceUpdate: forceUpdate); +// }); +// } - @override - void dispose() { - refreshSubscription?.cancel(); - super.dispose(); - } +// @override +// void didUpdateWidget(covariant AnalyticsListTile oldWidget) { +// super.didUpdateWidget(oldWidget); +// if (oldWidget.selected != widget.selected) { +// setTileData(); +// } +// } - Future setTileData({forceUpdate = false}) async { - tileData = await MatrixState.pangeaController.analytics.getAnalytics( - defaultSelected: widget.defaultSelected, - selected: widget.selected, - forceUpdate: forceUpdate, - ); - if (mounted) setState(() {}); - } +// @override +// void dispose() { +// refreshSubscription?.cancel(); +// super.dispose(); +// } - @override - Widget build(BuildContext context) { - final Room? room = - Matrix.of(context).client.getRoomById(widget.selected.id); - return Material( - color: widget.isSelected - ? Theme.of(context).colorScheme.secondaryContainer - : Colors.transparent, - child: ListTile( - leading: widget.selected.type == AnalyticsEntryType.privateChats - ? CircleAvatar( - backgroundColor: Theme.of(context).primaryColor, - foregroundColor: Colors.white, - radius: Avatar.defaultSize / 2, - child: const Icon(Icons.forum), - ) - : Avatar( - mxContent: widget.avatar, - name: widget.selected.displayName, - littleIcon: room?.roomTypeIcon, - ), - title: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - widget.selected.displayName, - maxLines: 1, - overflow: TextOverflow.ellipsis, - softWrap: false, - style: TextStyle( - fontWeight: FontWeight.bold, - color: Theme.of(context).textTheme.bodyLarge!.color, - ), - ), - ), - Tooltip( - message: L10n.of(context)!.timeOfLastMessage, - child: Text( - tileData?.lastMessageTime?.localizedTimeShort(context) ?? "", - style: TextStyle( - fontSize: 13, - color: Theme.of(context).textTheme.bodyMedium!.color, - ), - ), - ), - ], - ), - subtitle: ListSummaryAnalytics( - chartAnalytics: tileData, - ), - selected: widget.isSelected, - onTap: () { - if (widget.controller?.widget.selectedView == null) { - widget.onTap(widget.selected); - return; - } - if ((room?.isSpace ?? false) && widget.allowNavigateOnSelect) { - context.go('/rooms/analytics/${room!.id}'); - return; - } - widget.onTap(widget.selected); - }, - trailing: (room?.isSpace ?? false) && - widget.selected.type != AnalyticsEntryType.privateChats && - widget.allowNavigateOnSelect - ? const Icon(Icons.chevron_right) - : null, - ), - ); - } -} +// Future setTileData({forceUpdate = false}) async { +// tileData = await MatrixState.pangeaController.analytics.getAnalytics( +// defaultSelected: widget.defaultSelected, +// selected: widget.selected, +// forceUpdate: forceUpdate, +// ); +// if (mounted) setState(() {}); +// } + +// @override +// Widget build(BuildContext context) { +// final Room? room = +// Matrix.of(context).client.getRoomById(widget.selected.id); +// return Material( +// color: widget.isSelected +// ? Theme.of(context).colorScheme.secondaryContainer +// : Colors.transparent, +// child: ListTile( +// leading: widget.selected.type == AnalyticsEntryType.privateChats +// ? CircleAvatar( +// backgroundColor: Theme.of(context).primaryColor, +// foregroundColor: Colors.white, +// radius: Avatar.defaultSize / 2, +// child: const Icon(Icons.forum), +// ) +// : Avatar( +// mxContent: widget.avatar, +// name: widget.selected.displayName, +// littleIcon: room?.roomTypeIcon, +// ), +// title: Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Expanded( +// child: Text( +// widget.selected.displayName, +// maxLines: 1, +// overflow: TextOverflow.ellipsis, +// softWrap: false, +// style: TextStyle( +// fontWeight: FontWeight.bold, +// color: Theme.of(context).textTheme.bodyLarge!.color, +// ), +// ), +// ), +// Tooltip( +// message: L10n.of(context)!.timeOfLastMessage, +// child: Text( +// tileData?.lastMessageTime?.localizedTimeShort(context) ?? "", +// style: TextStyle( +// fontSize: 13, +// color: Theme.of(context).textTheme.bodyMedium!.color, +// ), +// ), +// ), +// ], +// ), +// subtitle: ListSummaryAnalytics( +// chartAnalytics: tileData, +// ), +// selected: widget.isSelected, +// onTap: () { +// if (widget.controller?.widget.selectedView == null) { +// widget.onTap(widget.selected); +// return; +// } +// if ((room?.isSpace ?? false) && widget.allowNavigateOnSelect) { +// context.go('/rooms/analytics/${room!.id}'); +// return; +// } +// widget.onTap(widget.selected); +// }, +// trailing: (room?.isSpace ?? false) && +// widget.selected.type != AnalyticsEntryType.privateChats && +// widget.allowNavigateOnSelect +// ? const Icon(Icons.chevron_right) +// : null, +// ), +// ); +// } +// } diff --git a/lib/pangea/pages/analytics/base_analytics.dart b/lib/pangea/pages/analytics/base_analytics.dart index cd41d2312..408505987 100644 --- a/lib/pangea/pages/analytics/base_analytics.dart +++ b/lib/pangea/pages/analytics/base_analytics.dart @@ -1,214 +1,214 @@ -import 'dart:async'; +// import 'dart:async'; -import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; -import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/models/analytics/analytics_event.dart'; -import 'package:fluffychat/pangea/models/language_model.dart'; -import 'package:fluffychat/pangea/pages/analytics/base_analytics_view.dart'; -import 'package:fluffychat/pangea/pages/analytics/student_analytics/student_analytics.dart'; -import 'package:flutter/material.dart'; -import 'package:future_loading_dialog/future_loading_dialog.dart'; -import 'package:matrix/matrix.dart'; +// import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; +// import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; +// import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; +// import 'package:fluffychat/pangea/models/analytics/analytics_event.dart'; +// import 'package:fluffychat/pangea/models/language_model.dart'; +// import 'package:fluffychat/pangea/pages/analytics/base_analytics_view.dart'; +// import 'package:fluffychat/pangea/pages/analytics/student_analytics/student_analytics.dart'; +// import 'package:flutter/material.dart'; +// import 'package:future_loading_dialog/future_loading_dialog.dart'; +// import 'package:matrix/matrix.dart'; -import '../../../widgets/matrix.dart'; -import '../../controllers/pangea_controller.dart'; -import '../../enum/bar_chart_view_enum.dart'; -import '../../enum/time_span.dart'; -import '../../models/analytics/chart_analytics_model.dart'; +// import '../../../widgets/matrix.dart'; +// import '../../controllers/pangea_controller.dart'; +// import '../../enum/bar_chart_view_enum.dart'; +// import '../../enum/time_span.dart'; +// import '../../models/analytics/chart_analytics_model.dart'; -class BaseAnalyticsPage extends StatefulWidget { - final String pageTitle; - final List tabs; - final BarChartViewSelection selectedView; +// class BaseAnalyticsPage extends StatefulWidget { +// final String pageTitle; +// final List tabs; +// final BarChartViewSelection selectedView; - final AnalyticsSelected defaultSelected; - final AnalyticsSelected? alwaysSelected; - final StudentAnalyticsController? myAnalyticsController; - final List targetLanguages; +// final AnalyticsSelected defaultSelected; +// final AnalyticsSelected? alwaysSelected; +// final StudentAnalyticsController? myAnalyticsController; +// final List targetLanguages; - BaseAnalyticsPage({ - super.key, - required this.pageTitle, - required this.tabs, - required this.alwaysSelected, - required this.defaultSelected, - required this.selectedView, - this.myAnalyticsController, - targetLanguages, - }) : targetLanguages = (targetLanguages?.isNotEmpty ?? false) - ? targetLanguages - : MatrixState.pangeaController.pLanguageStore.targetOptions; +// BaseAnalyticsPage({ +// super.key, +// required this.pageTitle, +// required this.tabs, +// required this.alwaysSelected, +// required this.defaultSelected, +// required this.selectedView, +// this.myAnalyticsController, +// targetLanguages, +// }) : targetLanguages = (targetLanguages?.isNotEmpty ?? false) +// ? targetLanguages +// : MatrixState.pangeaController.pLanguageStore.targetOptions; - @override - State createState() => BaseAnalyticsController(); -} +// @override +// State createState() => BaseAnalyticsController(); +// } -class BaseAnalyticsController extends State { - final PangeaController pangeaController = MatrixState.pangeaController; - AnalyticsSelected? selected; - String? currentLemma; - ChartAnalyticsModel? chartData; - StreamController refreshStream = StreamController.broadcast(); - BarChartViewSelection currentView = BarChartViewSelection.messages; +// class BaseAnalyticsController extends State { +// final PangeaController pangeaController = MatrixState.pangeaController; +// AnalyticsSelected? selected; +// String? currentLemma; +// ChartAnalyticsModel? chartData; +// StreamController refreshStream = StreamController.broadcast(); +// BarChartViewSelection currentView = BarChartViewSelection.messages; - bool isSelected(String chatOrStudentId) => chatOrStudentId == selected?.id; +// bool isSelected(String chatOrStudentId) => chatOrStudentId == selected?.id; - Room? get activeSpace { - if (widget.defaultSelected.type == AnalyticsEntryType.space) { - return Matrix.of(context).client.getRoomById(widget.defaultSelected.id); - } - return null; - } +// Room? get activeSpace { +// if (widget.defaultSelected.type == AnalyticsEntryType.space) { +// return Matrix.of(context).client.getRoomById(widget.defaultSelected.id); +// } +// return null; +// } - @override - void initState() { - super.initState(); - currentView = widget.selectedView; - if (widget.defaultSelected.type == AnalyticsEntryType.student) { - runFirstRefresh(); - } - setChartData(); - } +// @override +// void initState() { +// super.initState(); +// currentView = widget.selectedView; +// if (widget.defaultSelected.type == AnalyticsEntryType.student) { +// runFirstRefresh(); +// } +// setChartData(); +// } - @override - void didUpdateWidget(covariant BaseAnalyticsPage oldWidget) { - // when a user is a parent space's analytics and clicks on a subspace - super.didUpdateWidget(oldWidget); - if (oldWidget.defaultSelected.id != widget.defaultSelected.id) { - setChartData(); - refreshStream.add(false); - } - } +// @override +// void didUpdateWidget(covariant BaseAnalyticsPage oldWidget) { +// // when a user is a parent space's analytics and clicks on a subspace +// super.didUpdateWidget(oldWidget); +// if (oldWidget.defaultSelected.id != widget.defaultSelected.id) { +// setChartData(); +// refreshStream.add(false); +// } +// } - Future runFirstRefresh() async { - final analyticsRooms = - pangeaController.matrixState.client.allMyAnalyticsRooms; +// Future runFirstRefresh() async { +// final analyticsRooms = +// pangeaController.matrixState.client.allMyAnalyticsRooms; - final List analyticsEvent = []; - for (final analyticsRoom in analyticsRooms) { - final lastSummaryEvent = await analyticsRoom.getLastAnalyticsEvent( - PangeaEventTypes.summaryAnalytics, - Matrix.of(context).client.userID!, - ); - final lastConstructEvent = await analyticsRoom.getLastAnalyticsEvent( - PangeaEventTypes.construct, - Matrix.of(context).client.userID!, - ); - if (lastSummaryEvent != null) { - analyticsEvent.add(lastSummaryEvent); - } - if (lastConstructEvent != null) { - analyticsEvent.add(lastConstructEvent); - } - } +// final List analyticsEvent = []; +// for (final analyticsRoom in analyticsRooms) { +// final lastSummaryEvent = await analyticsRoom.getLastAnalyticsEvent( +// PangeaEventTypes.summaryAnalytics, +// Matrix.of(context).client.userID!, +// ); +// final lastConstructEvent = await analyticsRoom.getLastAnalyticsEvent( +// PangeaEventTypes.construct, +// Matrix.of(context).client.userID!, +// ); +// if (lastSummaryEvent != null) { +// analyticsEvent.add(lastSummaryEvent); +// } +// if (lastConstructEvent != null) { +// analyticsEvent.add(lastConstructEvent); +// } +// } - if (analyticsEvent.isNotEmpty) return; - onRefresh(); - } +// if (analyticsEvent.isNotEmpty) return; +// onRefresh(); +// } - Future onRefresh() async { - // postframe callback to avoid calling this function during build - WidgetsBinding.instance.addPostFrameCallback((_) async { - await showFutureLoadingDialog( - context: context, - future: () async { - debugPrint("updating analytics"); - await pangeaController.myAnalytics.updateAnalytics(); - await setChartData(forceUpdate: true); - refreshStream.add(true); - }, - ); - }); - } +// Future onRefresh() async { +// // postframe callback to avoid calling this function during build +// WidgetsBinding.instance.addPostFrameCallback((_) async { +// await showFutureLoadingDialog( +// context: context, +// future: () async { +// debugPrint("updating analytics"); +// await pangeaController.myAnalytics.updateAnalytics(); +// await setChartData(forceUpdate: true); +// refreshStream.add(true); +// }, +// ); +// }); +// } - Future fetchChartData( - AnalyticsSelected? params, { - forceUpdate = false, - }) async { - final ChartAnalyticsModel data = - await pangeaController.analytics.getAnalytics( - defaultSelected: widget.defaultSelected, - selected: params, - forceUpdate: forceUpdate, - ); +// Future fetchChartData( +// AnalyticsSelected? params, { +// forceUpdate = false, +// }) async { +// final ChartAnalyticsModel data = +// await pangeaController.analytics.getAnalytics( +// defaultSelected: widget.defaultSelected, +// selected: params, +// forceUpdate: forceUpdate, +// ); - return data; - } +// return data; +// } - Future setChartData({forceUpdate = false}) async { - final ChartAnalyticsModel newData = await fetchChartData( - selected, - forceUpdate: forceUpdate, - ); - setState(() => chartData = newData); - } +// Future setChartData({forceUpdate = false}) async { +// final ChartAnalyticsModel newData = await fetchChartData( +// selected, +// forceUpdate: forceUpdate, +// ); +// setState(() => chartData = newData); +// } - TimeSpan get currentTimeSpan => - pangeaController.analytics.currentAnalyticsTimeSpan; +// TimeSpan get currentTimeSpan => +// pangeaController.analytics.currentAnalyticsTimeSpan; - Future toggleSelection(AnalyticsSelected selectedParam) async { - setState(() { - debugPrint("selectedParam.id is ${selectedParam.id}"); - currentLemma = null; - selected = isSelected(selectedParam.id) ? null : selectedParam; - }); - await setChartData(); - refreshStream.add(false); - Future.delayed(Duration.zero, () => setState(() {})); - } +// Future toggleSelection(AnalyticsSelected selectedParam) async { +// setState(() { +// debugPrint("selectedParam.id is ${selectedParam.id}"); +// currentLemma = null; +// selected = isSelected(selectedParam.id) ? null : selectedParam; +// }); +// await setChartData(); +// refreshStream.add(false); +// Future.delayed(Duration.zero, () => setState(() {})); +// } - Future toggleTimeSpan(BuildContext context, TimeSpan timeSpan) async { - await pangeaController.analytics.setCurrentAnalyticsTimeSpan(timeSpan); - await setChartData(); - refreshStream.add(false); - } +// Future toggleTimeSpan(BuildContext context, TimeSpan timeSpan) async { +// await pangeaController.analytics.setCurrentAnalyticsTimeSpan(timeSpan); +// await setChartData(); +// refreshStream.add(false); +// } - Future toggleSpaceLang(LanguageModel lang) async { - await pangeaController.analytics.setCurrentAnalyticsLang(lang); - await setChartData(); - refreshStream.add(false); - } +// Future toggleSpaceLang(LanguageModel lang) async { +// await pangeaController.analytics.setCurrentAnalyticsLang(lang); +// await setChartData(); +// refreshStream.add(false); +// } - Future toggleView(BarChartViewSelection view) async { - currentView = view; - await setChartData(); - refreshStream.add(false); - } +// Future toggleView(BarChartViewSelection view) async { +// currentView = view; +// await setChartData(); +// refreshStream.add(false); +// } - void setCurrentLemma(String? lemma) { - currentLemma = lemma; - setState(() {}); - refreshStream.add(false); - } +// void setCurrentLemma(String? lemma) { +// currentLemma = lemma; +// setState(() {}); +// refreshStream.add(false); +// } - @override - Widget build(BuildContext context) { - return BaseAnalyticsView(controller: this); - } -} +// @override +// Widget build(BuildContext context) { +// return BaseAnalyticsView(controller: this); +// } +// } -class TabData { - AnalyticsEntryType type; - IconData icon; - List items; - bool allowNavigateOnSelect; +// class TabData { +// AnalyticsEntryType type; +// IconData icon; +// List items; +// bool allowNavigateOnSelect; - TabData({ - required this.type, - required this.items, - required this.icon, - this.allowNavigateOnSelect = true, - }); -} +// TabData({ +// required this.type, +// required this.items, +// required this.icon, +// this.allowNavigateOnSelect = true, +// }); +// } -class TabItem { - Uri? avatar; - String displayName; - String id; +// class TabItem { +// Uri? avatar; +// String displayName; +// String id; - TabItem({required this.avatar, required this.displayName, required this.id}); -} +// TabItem({required this.avatar, required this.displayName, required this.id}); +// } enum AnalyticsEntryType { student, room, space, privateChats } diff --git a/lib/pangea/pages/analytics/base_analytics_view.dart b/lib/pangea/pages/analytics/base_analytics_view.dart index 13e49aa38..60e31c5c8 100644 --- a/lib/pangea/pages/analytics/base_analytics_view.dart +++ b/lib/pangea/pages/analytics/base_analytics_view.dart @@ -1,243 +1,243 @@ -import 'dart:math'; +// import 'dart:math'; -import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; -import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; -import 'package:fluffychat/pangea/enum/time_span.dart'; -import 'package:fluffychat/pangea/pages/analytics/analytics_language_button.dart'; -import 'package:fluffychat/pangea/pages/analytics/analytics_list_tile.dart'; -import 'package:fluffychat/pangea/pages/analytics/analytics_view_button.dart'; -import 'package:fluffychat/pangea/pages/analytics/base_analytics.dart'; -import 'package:fluffychat/pangea/pages/analytics/construct_list.dart'; -import 'package:fluffychat/pangea/pages/analytics/messages_bar_chart.dart'; -import 'package:fluffychat/pangea/pages/analytics/time_span_menu_button.dart'; -import 'package:fluffychat/widgets/layouts/max_width_body.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; +// import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; +// import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +// import 'package:fluffychat/pangea/enum/time_span.dart'; +// import 'package:fluffychat/pangea/pages/analytics/analytics_language_button.dart'; +// import 'package:fluffychat/pangea/pages/analytics/analytics_list_tile.dart'; +// import 'package:fluffychat/pangea/pages/analytics/analytics_view_button.dart'; +// import 'package:fluffychat/pangea/pages/analytics/base_analytics.dart'; +// import 'package:fluffychat/pangea/pages/analytics/construct_list.dart'; +// import 'package:fluffychat/pangea/pages/analytics/messages_bar_chart.dart'; +// import 'package:fluffychat/pangea/pages/analytics/time_span_menu_button.dart'; +// import 'package:fluffychat/widgets/layouts/max_width_body.dart'; +// import 'package:flutter/gestures.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_gen/gen_l10n/l10n.dart'; +// import 'package:go_router/go_router.dart'; -class BaseAnalyticsView extends StatelessWidget { - const BaseAnalyticsView({ - super.key, - required this.controller, - }); +// class BaseAnalyticsView extends StatelessWidget { +// const BaseAnalyticsView({ +// super.key, +// required this.controller, +// }); - final BaseAnalyticsController controller; +// final BaseAnalyticsController controller; - Widget chartView(BuildContext context) { - switch (controller.currentView) { - case BarChartViewSelection.messages: - return MessagesBarChart( - chartAnalytics: controller.chartData, - ); - case BarChartViewSelection.grammar: - return ConstructList( - constructType: ConstructTypeEnum.grammar, - defaultSelected: controller.widget.defaultSelected, - selected: controller.selected, - controller: controller, - pangeaController: controller.pangeaController, - refreshStream: controller.refreshStream, - ); - } - } +// Widget chartView(BuildContext context) { +// switch (controller.currentView) { +// case BarChartViewSelection.messages: +// return MessagesBarChart( +// chartAnalytics: controller.chartData, +// ); +// case BarChartViewSelection.grammar: +// return ConstructList( +// constructType: ConstructTypeEnum.grammar, +// defaultSelected: controller.widget.defaultSelected, +// selected: controller.selected, +// controller: controller, +// pangeaController: controller.pangeaController, +// refreshStream: controller.refreshStream, +// ); +// } +// } - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - centerTitle: true, - title: RichText( - text: TextSpan( - style: TextStyle( - color: Theme.of(context).textTheme.bodyLarge!.color, - fontSize: 18, - fontWeight: FontWeight.w700, - ), - children: [ - TextSpan( - text: controller.widget.pageTitle, - style: const TextStyle(decoration: TextDecoration.underline), - recognizer: TapGestureRecognizer() - ..onTap = () { - final String route = - "/rooms/${controller.widget.defaultSelected.type.route}"; - context.go(route); - }, - ), - if (controller.activeSpace != null) - const TextSpan( - text: " > ", - ), - if (controller.activeSpace != null) - TextSpan( - text: controller.activeSpace!.getLocalizedDisplayname(), - ), - const TextSpan( - text: " > ", - ), - TextSpan( - text: controller.currentView.string(context), - ), - ], - ), - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.center, - ), - ), - body: MaxWidthBody( - withScrolling: false, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - TimeSpanMenuButton( - value: controller.currentTimeSpan, - onChange: (TimeSpan value) => - controller.toggleTimeSpan(context, value), - ), - AnalyticsViewButton( - value: controller.currentView, - onChange: controller.toggleView, - ), - AnalyticsLanguageButton( - value: controller - .pangeaController.analytics.currentAnalyticsLang, - onChange: (lang) => controller.toggleSpaceLang(lang), - languages: controller.widget.targetLanguages, - ), - ], - ), - const SizedBox( - height: 10, - ), - Expanded( - flex: 1, - child: chartView(context), - ), - Expanded( - flex: 1, - child: DefaultTabController( - length: 2, - child: Column( - children: [ - TabBar( - tabs: [ - ...controller.widget.tabs.map( - (tab) => Tab( - icon: Icon( - tab.icon, - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, - ), - ), - ), - ], - ), - Expanded( - child: SingleChildScrollView( - child: SizedBox( - height: max( - controller.widget.tabs[0].items.length + 1, - controller.widget.tabs[1].items.length, - ) * - 72, - child: TabBarView( - physics: const NeverScrollableScrollPhysics(), - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ...controller.widget.tabs[0].items.map( - (item) => AnalyticsListTile( - refreshStream: controller.refreshStream, - avatar: item.avatar, - defaultSelected: - controller.widget.defaultSelected, - selected: AnalyticsSelected( - item.id, - controller.widget.tabs[0].type, - item.displayName, - ), - isSelected: - controller.isSelected(item.id), - onTap: (_) => controller.toggleSelection( - AnalyticsSelected( - item.id, - controller.widget.tabs[0].type, - item.displayName, - ), - ), - allowNavigateOnSelect: controller - .widget.tabs[0].allowNavigateOnSelect, - pangeaController: - controller.pangeaController, - controller: controller, - ), - ), - if (controller.widget.defaultSelected.type == - AnalyticsEntryType.space) - AnalyticsListTile( - refreshStream: controller.refreshStream, - defaultSelected: - controller.widget.defaultSelected, - avatar: null, - selected: AnalyticsSelected( - controller.widget.defaultSelected.id, - AnalyticsEntryType.privateChats, - L10n.of(context)!.allPrivateChats, - ), - allowNavigateOnSelect: false, - isSelected: controller.isSelected( - controller.widget.defaultSelected.id, - ), - onTap: controller.toggleSelection, - pangeaController: - controller.pangeaController, - controller: controller, - ), - ], - ), - Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: controller.widget.tabs[1].items - .map( - (item) => AnalyticsListTile( - refreshStream: controller.refreshStream, - avatar: item.avatar, - defaultSelected: - controller.widget.defaultSelected, - selected: AnalyticsSelected( - item.id, - controller.widget.tabs[1].type, - item.displayName, - ), - isSelected: - controller.isSelected(item.id), - onTap: controller.toggleSelection, - allowNavigateOnSelect: controller.widget - .tabs[1].allowNavigateOnSelect, - pangeaController: - controller.pangeaController, - controller: controller, - ), - ) - .toList(), - ), - ], - ), - ), - ), - ), - ], - ), - ), - ), - ], - ), - ), - ); - } -} +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// appBar: AppBar( +// centerTitle: true, +// title: RichText( +// text: TextSpan( +// style: TextStyle( +// color: Theme.of(context).textTheme.bodyLarge!.color, +// fontSize: 18, +// fontWeight: FontWeight.w700, +// ), +// children: [ +// TextSpan( +// text: controller.widget.pageTitle, +// style: const TextStyle(decoration: TextDecoration.underline), +// recognizer: TapGestureRecognizer() +// ..onTap = () { +// final String route = +// "/rooms/${controller.widget.defaultSelected.type.route}"; +// context.go(route); +// }, +// ), +// if (controller.activeSpace != null) +// const TextSpan( +// text: " > ", +// ), +// if (controller.activeSpace != null) +// TextSpan( +// text: controller.activeSpace!.getLocalizedDisplayname(), +// ), +// const TextSpan( +// text: " > ", +// ), +// TextSpan( +// text: controller.currentView.string(context), +// ), +// ], +// ), +// overflow: TextOverflow.ellipsis, +// textAlign: TextAlign.center, +// ), +// ), +// body: MaxWidthBody( +// withScrolling: false, +// child: Column( +// children: [ +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// TimeSpanMenuButton( +// value: controller.currentTimeSpan, +// onChange: (TimeSpan value) => +// controller.toggleTimeSpan(context, value), +// ), +// AnalyticsViewButton( +// value: controller.currentView, +// onChange: controller.toggleView, +// ), +// AnalyticsLanguageButton( +// value: controller +// .pangeaController.analytics.currentAnalyticsLang, +// onChange: (lang) => controller.toggleSpaceLang(lang), +// languages: controller.widget.targetLanguages, +// ), +// ], +// ), +// const SizedBox( +// height: 10, +// ), +// Expanded( +// flex: 1, +// child: chartView(context), +// ), +// Expanded( +// flex: 1, +// child: DefaultTabController( +// length: 2, +// child: Column( +// children: [ +// TabBar( +// tabs: [ +// ...controller.widget.tabs.map( +// (tab) => Tab( +// icon: Icon( +// tab.icon, +// color: Theme.of(context) +// .colorScheme +// .onSurfaceVariant, +// ), +// ), +// ), +// ], +// ), +// Expanded( +// child: SingleChildScrollView( +// child: SizedBox( +// height: max( +// controller.widget.tabs[0].items.length + 1, +// controller.widget.tabs[1].items.length, +// ) * +// 72, +// child: TabBarView( +// physics: const NeverScrollableScrollPhysics(), +// children: [ +// Column( +// crossAxisAlignment: CrossAxisAlignment.stretch, +// children: [ +// ...controller.widget.tabs[0].items.map( +// (item) => AnalyticsListTile( +// refreshStream: controller.refreshStream, +// avatar: item.avatar, +// defaultSelected: +// controller.widget.defaultSelected, +// selected: AnalyticsSelected( +// item.id, +// controller.widget.tabs[0].type, +// item.displayName, +// ), +// isSelected: +// controller.isSelected(item.id), +// onTap: (_) => controller.toggleSelection( +// AnalyticsSelected( +// item.id, +// controller.widget.tabs[0].type, +// item.displayName, +// ), +// ), +// allowNavigateOnSelect: controller +// .widget.tabs[0].allowNavigateOnSelect, +// pangeaController: +// controller.pangeaController, +// controller: controller, +// ), +// ), +// if (controller.widget.defaultSelected.type == +// AnalyticsEntryType.space) +// AnalyticsListTile( +// refreshStream: controller.refreshStream, +// defaultSelected: +// controller.widget.defaultSelected, +// avatar: null, +// selected: AnalyticsSelected( +// controller.widget.defaultSelected.id, +// AnalyticsEntryType.privateChats, +// L10n.of(context)!.allPrivateChats, +// ), +// allowNavigateOnSelect: false, +// isSelected: controller.isSelected( +// controller.widget.defaultSelected.id, +// ), +// onTap: controller.toggleSelection, +// pangeaController: +// controller.pangeaController, +// controller: controller, +// ), +// ], +// ), +// Column( +// crossAxisAlignment: CrossAxisAlignment.stretch, +// children: controller.widget.tabs[1].items +// .map( +// (item) => AnalyticsListTile( +// refreshStream: controller.refreshStream, +// avatar: item.avatar, +// defaultSelected: +// controller.widget.defaultSelected, +// selected: AnalyticsSelected( +// item.id, +// controller.widget.tabs[1].type, +// item.displayName, +// ), +// isSelected: +// controller.isSelected(item.id), +// onTap: controller.toggleSelection, +// allowNavigateOnSelect: controller.widget +// .tabs[1].allowNavigateOnSelect, +// pangeaController: +// controller.pangeaController, +// controller: controller, +// ), +// ) +// .toList(), +// ), +// ], +// ), +// ), +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ), +// ), +// ); +// } +// } diff --git a/lib/pangea/pages/analytics/construct_list.dart b/lib/pangea/pages/analytics/construct_list.dart index 1848e7ada..497e60cc0 100644 --- a/lib/pangea/pages/analytics/construct_list.dart +++ b/lib/pangea/pages/analytics/construct_list.dart @@ -4,9 +4,10 @@ import 'package:collection/collection.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/time_span.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_representation_event.dart'; -import 'package:fluffychat/pangea/models/analytics/constructs_event.dart'; +import 'package:fluffychat/pangea/models/analytics/construct_list_model.dart'; import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; import 'package:fluffychat/pangea/models/pangea_match_model.dart'; import 'package:fluffychat/pangea/pages/analytics/base_analytics.dart'; @@ -22,7 +23,7 @@ class ConstructList extends StatefulWidget { final ConstructTypeEnum constructType; final AnalyticsSelected defaultSelected; final AnalyticsSelected? selected; - final BaseAnalyticsController controller; + final TimeSpan timeSpan; final PangeaController pangeaController; final StreamController refreshStream; @@ -30,9 +31,9 @@ class ConstructList extends StatefulWidget { super.key, required this.constructType, required this.defaultSelected, - required this.controller, required this.pangeaController, required this.refreshStream, + required this.timeSpan, this.selected, }); @@ -53,11 +54,11 @@ class ConstructListState extends State { : Column( children: [ ConstructListView( - controller: widget.controller, pangeaController: widget.pangeaController, defaultSelected: widget.defaultSelected, selected: widget.selected, refreshStream: widget.refreshStream, + timeSpan: widget.timeSpan, ), ], ); @@ -74,17 +75,17 @@ class ConstructListState extends State { // subtitle = total uses, equal to construct.content.uses.length // list has a fixed height of 400 and is scrollable class ConstructListView extends StatefulWidget { - final BaseAnalyticsController controller; final PangeaController pangeaController; final AnalyticsSelected defaultSelected; + final TimeSpan timeSpan; final AnalyticsSelected? selected; final StreamController refreshStream; const ConstructListView({ super.key, - required this.controller, required this.pangeaController, required this.defaultSelected, + required this.timeSpan, required this.refreshStream, this.selected, }); @@ -101,6 +102,7 @@ class ConstructListViewState extends State { bool fetchingConstructs = true; bool fetchingUses = false; StreamSubscription? refreshSubscription; + String? currentLemma; @override void initState() { @@ -108,13 +110,17 @@ class ConstructListViewState extends State { widget.pangeaController.analytics .getConstructs( constructType: constructType, - removeIT: true, - defaultSelected: widget.defaultSelected, - selected: widget.selected, forceUpdate: true, ) .whenComplete(() => setState(() => fetchingConstructs = false)) - .then((value) => setState(() => _constructs = value)); + .then( + (value) => setState( + () => constructs = ConstructListModel( + type: constructType, + uses: value, + ), + ), + ); refreshSubscription = widget.refreshStream.stream.listen((forceUpdate) { // postframe callback to let widget rebuild with the new selected parameter @@ -123,14 +129,14 @@ class ConstructListViewState extends State { widget.pangeaController.analytics .getConstructs( constructType: constructType, - removeIT: true, - defaultSelected: widget.defaultSelected, - selected: widget.selected, forceUpdate: true, ) .then( (value) => setState(() { - _constructs = value; + ConstructListModel( + type: constructType, + uses: value, + ); }), ); }); @@ -143,22 +149,21 @@ class ConstructListViewState extends State { super.dispose(); } - int get lemmaIndex => - constructs?.indexWhere( - (element) => element.lemma == widget.controller.currentLemma, - ) ?? - -1; + void setCurrentLemma(String? lemma) { + currentLemma = lemma; + setState(() {}); + } Future getMessageEvent( OneConstructUse use, ) async { final Client client = Matrix.of(context).client; PangeaMessageEvent msgEvent; - if (_msgEventCache.containsKey(use.msgId!)) { - return _msgEventCache[use.msgId!]!; + if (_msgEventCache.containsKey(use.msgId)) { + return _msgEventCache[use.msgId]!; } final Room? msgRoom = use.getRoom(client); - if (msgRoom == null || use.msgId == null) { + if (msgRoom == null) { return null; } @@ -180,20 +185,25 @@ class ConstructListViewState extends State { timeline: timeline, ownMessage: event.senderId == client.userID, ); - _msgEventCache[use.msgId!] = msgEvent; + _msgEventCache[use.msgId] = msgEvent; return msgEvent; } Future fetchUses() async { if (fetchingUses) return; - if (currentConstruct == null) { + if (currentLemma == null) { setState(() => _msgEvents.clear()); return; } setState(() => fetchingUses = true); try { - final List uses = currentConstruct!.uses; + final List uses = constructs?.constructs + .firstWhereOrNull( + (element) => element.lemma == currentLemma, + ) + ?.uses ?? + []; _msgEvents.clear(); for (final OneConstructUse use in uses) { @@ -212,61 +222,19 @@ class ConstructListViewState extends State { ErrorHandler.logError( e: err, s: s, - m: "Failed to fetch uses for current construct ${currentConstruct?.lemma}", + m: "Failed to fetch uses for current construct $currentLemma", ); } } - List? _constructs; - - List? get constructs { - if (_constructs == null) { - return null; - } - - final List filtered = List.from(_constructs!) - .map((event) => event.content.uses) - .expand((uses) => uses) - .cast() - .where((use) => use.constructType == constructType) - .toList(); - - final Map> lemmaToUses = {}; - for (final use in filtered) { - if (use.lemma == null) continue; - lemmaToUses[use.lemma!] ??= []; - lemmaToUses[use.lemma!]!.add(use); - } - - final constructUses = lemmaToUses.entries - .map( - (entry) => ConstructUses( - lemma: entry.key, - uses: entry.value, - constructType: constructType, - ), - ) - .toList(); - - constructUses.sort((a, b) { - final comp = b.uses.length.compareTo(a.uses.length); - if (comp != 0) return comp; - return a.lemma.compareTo(b.lemma); - }); - - return constructUses; - } - - ConstructUses? get currentConstruct => constructs?.firstWhereOrNull( - (element) => element.lemma == widget.controller.currentLemma, - ); + ConstructListModel? constructs; // given the current lemma and list of message events, return a list of // MessageEventMatch objects, which contain one PangeaMessageEvent to one PangeaMatch // this is because some message events may have has more than one PangeaMatch of a // given lemma type. List getMessageEventMatches() { - if (widget.controller.currentLemma == null) return []; + if (currentLemma == null) return []; final List allMsgErrorSteps = []; for (final msgEvent in _msgEvents) { @@ -277,7 +245,7 @@ class ConstructListViewState extends State { } // get all the pangea matches in that message which have that lemma final List? msgErrorSteps = msgEvent.errorSteps( - widget.controller.currentLemma!, + currentLemma!, ); if (msgErrorSteps == null) continue; @@ -308,7 +276,7 @@ class ConstructListViewState extends State { ); } - if (constructs?.isEmpty ?? true) { + if (constructs?.constructs.isEmpty ?? true) { return Expanded( child: Center(child: Text(L10n.of(context)!.noDataFound)), ); @@ -316,18 +284,18 @@ class ConstructListViewState extends State { return Expanded( child: ListView.builder( - itemCount: constructs!.length, + itemCount: constructs!.constructs.length, itemBuilder: (context, index) { return ListTile( title: Text( - constructs![index].lemma, + constructs!.constructs[index].lemma, ), subtitle: Text( - '${L10n.of(context)!.total} ${constructs![index].uses.length}', + '${L10n.of(context)!.total} ${constructs!.constructs[index].uses.length}', ), onTap: () async { - final String lemma = constructs![index].lemma; - widget.controller.setCurrentLemma(lemma); + final String lemma = constructs!.constructs[index].lemma; + setCurrentLemma(lemma); fetchUses().then((_) => showConstructMessagesDialog()); }, ); @@ -346,20 +314,20 @@ class ConstructMessagesDialog extends StatelessWidget { @override Widget build(BuildContext context) { - if (controller.widget.controller.currentLemma == null || - controller.constructs == null || - controller.lemmaIndex < 0 || - controller.lemmaIndex >= controller.constructs!.length) { + if (controller.currentLemma == null || controller.constructs == null) { return const AlertDialog(content: CircularProgressIndicator.adaptive()); } final msgEventMatches = controller.getMessageEventMatches(); - final noData = controller.constructs![controller.lemmaIndex].uses.length > - controller._msgEvents.length; + final currentConstruct = controller.constructs!.constructs.firstWhereOrNull( + (construct) => construct.lemma == controller.currentLemma, + ); + final noData = currentConstruct == null || + currentConstruct.uses.length > controller._msgEvents.length; return AlertDialog( - title: Center(child: Text(controller.widget.controller.currentLemma!)), + title: Center(child: Text(controller.currentLemma!)), content: SizedBox( height: noData ? 90 : 250, width: noData ? 200 : 400, @@ -380,7 +348,7 @@ class ConstructMessagesDialog extends StatelessWidget { children: [ ConstructMessage( msgEvent: event.msgEvent, - lemma: controller.widget.controller.currentLemma!, + lemma: controller.currentLemma!, errorMessage: event.lemmaMatch, ), if (index < msgEventMatches.length - 1) @@ -528,42 +496,37 @@ class ConstructMessageBubble extends StatelessWidget { vertical: 8, ), child: RichText( - text: (end == null) - ? TextSpan( - text: errorText, - style: defaultStyle, - ) - : TextSpan( - children: [ - TextSpan( - text: errorText.substring(0, start), - style: defaultStyle, - ), - TextSpan( - text: errorText.substring(start, end), - style: defaultStyle.merge( - TextStyle( - backgroundColor: Colors.red.withOpacity(0.25), - decoration: TextDecoration.lineThrough, - decorationThickness: 2.5, - ), - ), - ), - const TextSpan(text: " "), - TextSpan( - text: replacementText, - style: defaultStyle.merge( - TextStyle( - backgroundColor: Colors.green.withOpacity(0.25), - ), - ), - ), - TextSpan( - text: errorText.substring(end), - style: defaultStyle, - ), - ], + text: TextSpan( + children: [ + TextSpan( + text: errorText.substring(0, start), + style: defaultStyle, + ), + TextSpan( + text: errorText.substring(start, end), + style: defaultStyle.merge( + TextStyle( + backgroundColor: Colors.red.withOpacity(0.25), + decoration: TextDecoration.lineThrough, + decorationThickness: 2.5, + ), ), + ), + const TextSpan(text: " "), + TextSpan( + text: replacementText, + style: defaultStyle.merge( + TextStyle( + backgroundColor: Colors.green.withOpacity(0.25), + ), + ), + ), + TextSpan( + text: errorText.substring(end), + style: defaultStyle, + ), + ], + ), ), ), ), diff --git a/lib/pangea/pages/analytics/list_summary_analytics.dart b/lib/pangea/pages/analytics/list_summary_analytics.dart index bf388cea7..02bb5d3fb 100644 --- a/lib/pangea/pages/analytics/list_summary_analytics.dart +++ b/lib/pangea/pages/analytics/list_summary_analytics.dart @@ -1,101 +1,101 @@ -import 'dart:math'; +// import 'dart:math'; -import 'package:fluffychat/pangea/models/analytics/chart_analytics_model.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; +// import 'package:fluffychat/pangea/models/analytics/chart_analytics_model.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_gen/gen_l10n/l10n.dart'; -import '../../enum/use_type.dart'; +// import '../../enum/use_type.dart'; -class ListSummaryAnalytics extends StatelessWidget { - final ChartAnalyticsModel? chartAnalytics; +// class ListSummaryAnalytics extends StatelessWidget { +// final ChartAnalyticsModel? chartAnalytics; - const ListSummaryAnalytics({super.key, this.chartAnalytics}); +// const ListSummaryAnalytics({super.key, this.chartAnalytics}); - TimeSeriesTotals? get totals => chartAnalytics?.totals; +// TimeSeriesTotals? get totals => chartAnalytics?.totals; - String spacer(int baseLength, int number) => - " " * max(baseLength - number.toString().length, 0); +// String spacer(int baseLength, int number) => +// " " * max(baseLength - number.toString().length, 0); - WidgetSpan spacerIconText( - String toolTip, - String space, - IconData icon, - int value, - Color? color, [ - percentage = true, - ]) => - WidgetSpan( - child: Tooltip( - message: toolTip, - child: RichText( - text: TextSpan( - children: [ - TextSpan( - text: space, - ), - WidgetSpan(child: Icon(icon, size: 14, color: color)), - TextSpan( - text: " $value${percentage ? "%" : ""}", - style: TextStyle(color: color), - ), - ], - ), - ), - ), - ); +// WidgetSpan spacerIconText( +// String toolTip, +// String space, +// IconData icon, +// int value, +// Color? color, [ +// percentage = true, +// ]) => +// WidgetSpan( +// child: Tooltip( +// message: toolTip, +// child: RichText( +// text: TextSpan( +// children: [ +// TextSpan( +// text: space, +// ), +// WidgetSpan(child: Icon(icon, size: 14, color: color)), +// TextSpan( +// text: " $value${percentage ? "%" : ""}", +// style: TextStyle(color: color), +// ), +// ], +// ), +// ), +// ), +// ); - @override - Widget build(BuildContext context) { - if (totals == null) { - return const LinearProgressIndicator(); - } - final l10n = L10n.of(context); +// @override +// Widget build(BuildContext context) { +// if (totals == null) { +// return const LinearProgressIndicator(); +// } +// final l10n = L10n.of(context); - return RichText( - text: TextSpan( - children: [ - spacerIconText( - L10n.of(context) != null - ? L10n.of(context)!.totalMessages - : "Total messages sent", - "", - Icons.chat_bubble, - totals!.all, - Theme.of(context).textTheme.bodyLarge!.color, - false, - ), - if (totals!.all != 0) ...[ - spacerIconText( - l10n != null ? l10n.taTooltip : "With translation assistance", - spacer(8, totals!.all), - UseType.ta.iconData, - totals!.taPercent, - UseType.ta.color(context), - ), - spacerIconText( - l10n != null ? l10n.gaTooltip : "With grammar assistance", - spacer(4, totals!.taPercent), - UseType.ga.iconData, - totals!.gaPercent, - UseType.ga.color(context), - ), - spacerIconText( - l10n != null ? l10n.waTooltip : "Without assistance", - spacer(4, totals!.gaPercent), - UseType.wa.iconData, - totals!.waPercent, - UseType.wa.color(context), - ), - spacerIconText( - l10n != null ? l10n.unTooltip : "Other", - spacer(4, totals!.waPercent), - UseType.un.iconData, - totals!.unPercent, - UseType.un.color(context), - ), - ], - ], - ), - ); - } -} +// return RichText( +// text: TextSpan( +// children: [ +// spacerIconText( +// L10n.of(context) != null +// ? L10n.of(context)!.totalMessages +// : "Total messages sent", +// "", +// Icons.chat_bubble, +// totals!.all, +// Theme.of(context).textTheme.bodyLarge!.color, +// false, +// ), +// if (totals!.all != 0) ...[ +// spacerIconText( +// l10n != null ? l10n.taTooltip : "With translation assistance", +// spacer(8, totals!.all), +// UseType.ta.iconData, +// totals!.taPercent, +// UseType.ta.color(context), +// ), +// spacerIconText( +// l10n != null ? l10n.gaTooltip : "With grammar assistance", +// spacer(4, totals!.taPercent), +// UseType.ga.iconData, +// totals!.gaPercent, +// UseType.ga.color(context), +// ), +// spacerIconText( +// l10n != null ? l10n.waTooltip : "Without assistance", +// spacer(4, totals!.gaPercent), +// UseType.wa.iconData, +// totals!.waPercent, +// UseType.wa.color(context), +// ), +// spacerIconText( +// l10n != null ? l10n.unTooltip : "Other", +// spacer(4, totals!.waPercent), +// UseType.un.iconData, +// totals!.unPercent, +// UseType.un.color(context), +// ), +// ], +// ], +// ), +// ); +// } +// } diff --git a/lib/pangea/pages/analytics/messages_bar_chart.dart b/lib/pangea/pages/analytics/messages_bar_chart.dart index 509270edb..5a9002243 100644 --- a/lib/pangea/pages/analytics/messages_bar_chart.dart +++ b/lib/pangea/pages/analytics/messages_bar_chart.dart @@ -1,402 +1,402 @@ -import 'dart:developer'; +// import 'dart:developer'; -import 'package:fl_chart/fl_chart.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/pangea/pages/analytics/bar_chart_placeholder_data.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; +// import 'package:fl_chart/fl_chart.dart'; +// import 'package:fluffychat/config/themes.dart'; +// import 'package:fluffychat/pangea/pages/analytics/bar_chart_placeholder_data.dart'; +// import 'package:fluffychat/pangea/utils/error_handler.dart'; +// import 'package:flutter/foundation.dart'; +// import 'package:flutter/material.dart'; +// import 'package:intl/intl.dart'; -import '../../enum/time_span.dart'; -import '../../enum/use_type.dart'; -import '../../models/analytics/chart_analytics_model.dart'; -import 'bar_chart_card.dart'; -import 'messages_legend_widget.dart'; +// import '../../enum/time_span.dart'; +// import '../../enum/use_type.dart'; +// import '../../models/analytics/chart_analytics_model.dart'; +// import 'bar_chart_card.dart'; +// import 'messages_legend_widget.dart'; -class MessagesBarChart extends StatefulWidget { - final ChartAnalyticsModel? chartAnalytics; +// class MessagesBarChart extends StatefulWidget { +// final ChartAnalyticsModel? chartAnalytics; - const MessagesBarChart({ - super.key, - required this.chartAnalytics, - }); +// const MessagesBarChart({ +// super.key, +// required this.chartAnalytics, +// }); - @override - State createState() => MessagesBarChartState(); -} +// @override +// State createState() => MessagesBarChartState(); +// } -class MessagesBarChartState extends State { - final double barSpace = 16; - final List> intervalGroupings = []; +// class MessagesBarChartState extends State { +// final double barSpace = 16; +// final List> intervalGroupings = []; - @override - initState() { - super.initState(); - } +// @override +// initState() { +// super.initState(); +// } - @override - Widget build(BuildContext context) { - final flLine = FlLine( - color: Theme.of(context).dividerColor, - strokeWidth: 1, - ); +// @override +// Widget build(BuildContext context) { +// final flLine = FlLine( +// color: Theme.of(context).dividerColor, +// strokeWidth: 1, +// ); - final flTitlesData = FlTitlesData( - show: true, - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 28, - getTitlesWidget: bottomTitles, - ), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 40, - getTitlesWidget: leftTitles, - ), - ), - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - rightTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - ); - final barChartData = BarChartData( - alignment: BarChartAlignment.spaceEvenly, - barTouchData: BarTouchData( - enabled: false, - ), - // barTouchData: barTouchData, - titlesData: flTitlesData, - gridData: FlGridData( - show: true, - // checkToShowHorizontalLine: (value) => value % 10 == 0, - checkToShowHorizontalLine: (value) => true, - getDrawingHorizontalLine: (value) => flLine, - checkToShowVerticalLine: (value) => false, - getDrawingVerticalLine: (value) => flLine, - ), - borderData: FlBorderData( - show: false, - ), - groupsSpace: barSpace, - barGroups: barChartGroupData, - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - ); - final barChart = BarChart( - barChartData, - swapAnimationDuration: const Duration(milliseconds: 250), - ); +// final flTitlesData = FlTitlesData( +// show: true, +// bottomTitles: AxisTitles( +// sideTitles: SideTitles( +// showTitles: true, +// reservedSize: 28, +// getTitlesWidget: bottomTitles, +// ), +// ), +// leftTitles: AxisTitles( +// sideTitles: SideTitles( +// showTitles: true, +// reservedSize: 40, +// getTitlesWidget: leftTitles, +// ), +// ), +// topTitles: const AxisTitles( +// sideTitles: SideTitles(showTitles: false), +// ), +// rightTitles: const AxisTitles( +// sideTitles: SideTitles(showTitles: false), +// ), +// ); +// final barChartData = BarChartData( +// alignment: BarChartAlignment.spaceEvenly, +// barTouchData: BarTouchData( +// enabled: false, +// ), +// // barTouchData: barTouchData, +// titlesData: flTitlesData, +// gridData: FlGridData( +// show: true, +// // checkToShowHorizontalLine: (value) => value % 10 == 0, +// checkToShowHorizontalLine: (value) => true, +// getDrawingHorizontalLine: (value) => flLine, +// checkToShowVerticalLine: (value) => false, +// getDrawingVerticalLine: (value) => flLine, +// ), +// borderData: FlBorderData( +// show: false, +// ), +// groupsSpace: barSpace, +// barGroups: barChartGroupData, +// backgroundColor: Theme.of(context).scaffoldBackgroundColor, +// ); +// final barChart = BarChart( +// barChartData, +// swapAnimationDuration: const Duration(milliseconds: 250), +// ); - return BarChartCard( - barChart: barChart, - loadingData: widget.chartAnalytics == null, - legend: const MessagesLegendsListWidget(), - ); - } +// return BarChartCard( +// barChart: barChart, +// loadingData: widget.chartAnalytics == null, +// legend: const MessagesLegendsListWidget(), +// ); +// } - bool showLabelBasedOnTimeSpan( - TimeSpan timeSpan, - TimeSeriesInterval current, - TimeSeriesInterval? last, - int labelIndex, - ) { - switch (timeSpan) { - case TimeSpan.day: - return current.end.hour % 3 == 0; - case TimeSpan.month: - if (current.end.month != last?.end.month) { - return true; - } - double width = MediaQuery.of(context).size.width; - if (FluffyThemes.isColumnMode(context)) { - width = width - FluffyThemes.navRailWidth - FluffyThemes.columnWidth; - } - const int numDays = 28; - const int minSpacePerDay = 20; - final int availableSpaces = width ~/ minSpacePerDay; - final int showAtInterval = (numDays / availableSpaces).floor() + 1; +// bool showLabelBasedOnTimeSpan( +// TimeSpan timeSpan, +// TimeSeriesInterval current, +// TimeSeriesInterval? last, +// int labelIndex, +// ) { +// switch (timeSpan) { +// case TimeSpan.day: +// return current.end.hour % 3 == 0; +// case TimeSpan.month: +// if (current.end.month != last?.end.month) { +// return true; +// } +// double width = MediaQuery.of(context).size.width; +// if (FluffyThemes.isColumnMode(context)) { +// width = width - FluffyThemes.navRailWidth - FluffyThemes.columnWidth; +// } +// const int numDays = 28; +// const int minSpacePerDay = 20; +// final int availableSpaces = width ~/ minSpacePerDay; +// final int showAtInterval = (numDays / availableSpaces).floor() + 1; - final int lastDayOfCurrentMonth = - DateTime(current.end.year, current.end.month + 1, 0).day; - final bool isNextToMonth = labelIndex == 1 || - current.end.day == 2 || - current.end.day == lastDayOfCurrentMonth; - final bool shouldShowNextToMonth = showAtInterval <= 1; - return (current.end.day % showAtInterval == 0) && - (!isNextToMonth || shouldShowNextToMonth); - case TimeSpan.week: - case TimeSpan.sixmonths: - case TimeSpan.year: - default: - return true; - } - } +// final int lastDayOfCurrentMonth = +// DateTime(current.end.year, current.end.month + 1, 0).day; +// final bool isNextToMonth = labelIndex == 1 || +// current.end.day == 2 || +// current.end.day == lastDayOfCurrentMonth; +// final bool shouldShowNextToMonth = showAtInterval <= 1; +// return (current.end.day % showAtInterval == 0) && +// (!isNextToMonth || shouldShowNextToMonth); +// case TimeSpan.week: +// case TimeSpan.sixmonths: +// case TimeSpan.year: +// default: +// return true; +// } +// } - String getLabelBasedOnTimeSpan( - TimeSpan timeSpan, - TimeSeriesInterval current, - TimeSeriesInterval? last, - int labelIndex, - ) { - final bool showLabel = showLabelBasedOnTimeSpan( - timeSpan, - current, - last, - labelIndex, - ); +// String getLabelBasedOnTimeSpan( +// TimeSpan timeSpan, +// TimeSeriesInterval current, +// TimeSeriesInterval? last, +// int labelIndex, +// ) { +// final bool showLabel = showLabelBasedOnTimeSpan( +// timeSpan, +// current, +// last, +// labelIndex, +// ); - if (widget.chartAnalytics == null || !showLabel) { - return ""; - } - if (isInSameGroup(last, current, timeSpan)) { - return "-"; - } +// if (widget.chartAnalytics == null || !showLabel) { +// return ""; +// } +// if (isInSameGroup(last, current, timeSpan)) { +// return "-"; +// } - switch (widget.chartAnalytics?.timeSpan ?? TimeSpan.month) { - case TimeSpan.day: - return DateFormat(DateFormat.HOUR).format(current.end); - case TimeSpan.week: - return DateFormat(DateFormat.ABBR_WEEKDAY).format(current.end); - case TimeSpan.month: - return current.end.month != last?.end.month - ? DateFormat(DateFormat.ABBR_MONTH).format(current.end) - : DateFormat(DateFormat.DAY).format(current.end); - case TimeSpan.sixmonths: - case TimeSpan.year: - return DateFormat(DateFormat.ABBR_STANDALONE_MONTH).format(current.end); - default: - return ''; - } - } +// switch (widget.chartAnalytics?.timeSpan ?? TimeSpan.month) { +// case TimeSpan.day: +// return DateFormat(DateFormat.HOUR).format(current.end); +// case TimeSpan.week: +// return DateFormat(DateFormat.ABBR_WEEKDAY).format(current.end); +// case TimeSpan.month: +// return current.end.month != last?.end.month +// ? DateFormat(DateFormat.ABBR_MONTH).format(current.end) +// : DateFormat(DateFormat.DAY).format(current.end); +// case TimeSpan.sixmonths: +// case TimeSpan.year: +// return DateFormat(DateFormat.ABBR_STANDALONE_MONTH).format(current.end); +// default: +// return ''; +// } +// } - Widget bottomTitles(double value, TitleMeta meta) { - if (widget.chartAnalytics == null) { - return Container(); - } - String text; - final index = value.toInt(); - final TimeSpan timeSpan = widget.chartAnalytics?.timeSpan ?? TimeSpan.month; - final TimeSeriesInterval? last = - index != 0 ? intervalGroupings[index - 1].last : null; - final TimeSeriesInterval current = intervalGroupings[index].last; +// Widget bottomTitles(double value, TitleMeta meta) { +// if (widget.chartAnalytics == null) { +// return Container(); +// } +// String text; +// final index = value.toInt(); +// final TimeSpan timeSpan = widget.chartAnalytics?.timeSpan ?? TimeSpan.month; +// final TimeSeriesInterval? last = +// index != 0 ? intervalGroupings[index - 1].last : null; +// final TimeSeriesInterval current = intervalGroupings[index].last; - text = getLabelBasedOnTimeSpan(timeSpan, current, last, index); +// text = getLabelBasedOnTimeSpan(timeSpan, current, last, index); - return SideTitleWidget( - axisSide: meta.axisSide, - child: Text( - text, - style: titleTextStyle(context), - ), - ); - } +// return SideTitleWidget( +// axisSide: meta.axisSide, +// child: Text( +// text, +// style: titleTextStyle(context), +// ), +// ); +// } - TextStyle titleTextStyle(context) => TextStyle( - color: Theme.of(context).textTheme.bodyLarge!.color, - fontSize: 10, - ); +// TextStyle titleTextStyle(context) => TextStyle( +// color: Theme.of(context).textTheme.bodyLarge!.color, +// fontSize: 10, +// ); - Widget leftTitles(double value, TitleMeta meta) { - Widget textWidget; - if (value != meta.max) { - textWidget = Text(meta.formattedValue, style: titleTextStyle(context)); - } else { - textWidget = const Icon(Icons.chat_bubble, size: 14); - } - return SideTitleWidget( - axisSide: meta.axisSide, - child: textWidget, - ); - } +// Widget leftTitles(double value, TitleMeta meta) { +// Widget textWidget; +// if (value != meta.max) { +// textWidget = Text(meta.formattedValue, style: titleTextStyle(context)); +// } else { +// textWidget = const Icon(Icons.chat_bubble, size: 14); +// } +// return SideTitleWidget( +// axisSide: meta.axisSide, +// child: textWidget, +// ); +// } - bool isInSameGroup( - TimeSeriesInterval? t1, - TimeSeriesInterval t2, - TimeSpan timeSpan, - ) { - final DateTime? date1 = t1?.end; - final DateTime date2 = t2.end; - if (timeSpan == TimeSpan.sixmonths || timeSpan == TimeSpan.year) { - return date1?.month == date2.month; - } else if (timeSpan == TimeSpan.week) { - return date1?.day == date2.day; - } else { - return false; - } - } +// bool isInSameGroup( +// TimeSeriesInterval? t1, +// TimeSeriesInterval t2, +// TimeSpan timeSpan, +// ) { +// final DateTime? date1 = t1?.end; +// final DateTime date2 = t2.end; +// if (timeSpan == TimeSpan.sixmonths || timeSpan == TimeSpan.year) { +// return date1?.month == date2.month; +// } else if (timeSpan == TimeSpan.week) { +// return date1?.day == date2.day; +// } else { +// return false; +// } +// } - void makeIntervalGroupings() { - intervalGroupings.clear(); - try { - for (final timeSeriesInterval - in widget.chartAnalytics?.timeSeries ?? []) { - //Note: if we decide we'd like to do some sort of grouping in the future, - // this is where that could happen. Currently, we're just putting one - // BarChartRod in each BarChartGroup - final TimeSeriesInterval? last = - intervalGroupings.isNotEmpty ? intervalGroupings.last.last : null; +// void makeIntervalGroupings() { +// intervalGroupings.clear(); +// try { +// for (final timeSeriesInterval +// in widget.chartAnalytics?.timeSeries ?? []) { +// //Note: if we decide we'd like to do some sort of grouping in the future, +// // this is where that could happen. Currently, we're just putting one +// // BarChartRod in each BarChartGroup +// final TimeSeriesInterval? last = +// intervalGroupings.isNotEmpty ? intervalGroupings.last.last : null; - if (widget.chartAnalytics != null && - isInSameGroup( - last, - timeSeriesInterval, - widget.chartAnalytics!.timeSpan, - )) { - intervalGroupings.last.add(timeSeriesInterval); - } else { - intervalGroupings.add([timeSeriesInterval]); - } - } - } catch (err, stack) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: stack); - } - } +// if (widget.chartAnalytics != null && +// isInSameGroup( +// last, +// timeSeriesInterval, +// widget.chartAnalytics!.timeSpan, +// )) { +// intervalGroupings.last.add(timeSeriesInterval); +// } else { +// intervalGroupings.add([timeSeriesInterval]); +// } +// } +// } catch (err, stack) { +// debugger(when: kDebugMode); +// ErrorHandler.logError(e: err, s: stack); +// } +// } - List get barChartGroupData { - if (widget.chartAnalytics == null) { - return BarChartPlaceHolderData.getRandomData(context); - } +// List get barChartGroupData { +// if (widget.chartAnalytics == null) { +// return BarChartPlaceHolderData.getRandomData(context); +// } - makeIntervalGroupings(); +// makeIntervalGroupings(); - final List chartData = []; +// final List chartData = []; - intervalGroupings.asMap().forEach((index, intervalGroup) { - chartData.add( - BarChartGroupData( - x: index, - barsSpace: barSpace, - // barRods: intervalGroup.map(constructBarChartRodData).toList(), - barRods: constructBarChartRodData(intervalGroup), - ), - ); - }); - return chartData; - } +// intervalGroupings.asMap().forEach((index, intervalGroup) { +// chartData.add( +// BarChartGroupData( +// x: index, +// barsSpace: barSpace, +// // barRods: intervalGroup.map(constructBarChartRodData).toList(), +// barRods: constructBarChartRodData(intervalGroup), +// ), +// ); +// }); +// return chartData; +// } - // BarChartRodData constructBarChartRodData(TimeSeriesInterval timeSeriesInterval) { - // final double y1 = timeSeriesInterval.spanIT.toDouble(); - // final double y2 = - // (timeSeriesInterval.spanIT + timeSeriesInterval.spanIGC).toDouble(); - // final double y3 = timeSeriesInterval.spanTotal.toDouble(); - // return BarChartRodData( - // toY: y3, - // width: 10.toDouble(), - // rodStackItems: [ - // BarChartRodStackItem(0, y1, UseType.ta.color(context)), - // BarChartRodStackItem(y1, y2, UseType.ga.color(context)), - // BarChartRodStackItem(y2, y3, UseType.wa.color(context)), - // ], - // borderRadius: BorderRadius.zero, - // ); - // } +// // BarChartRodData constructBarChartRodData(TimeSeriesInterval timeSeriesInterval) { +// // final double y1 = timeSeriesInterval.spanIT.toDouble(); +// // final double y2 = +// // (timeSeriesInterval.spanIT + timeSeriesInterval.spanIGC).toDouble(); +// // final double y3 = timeSeriesInterval.spanTotal.toDouble(); +// // return BarChartRodData( +// // toY: y3, +// // width: 10.toDouble(), +// // rodStackItems: [ +// // BarChartRodStackItem(0, y1, UseType.ta.color(context)), +// // BarChartRodStackItem(y1, y2, UseType.ga.color(context)), +// // BarChartRodStackItem(y2, y3, UseType.wa.color(context)), +// // ], +// // borderRadius: BorderRadius.zero, +// // ); +// // } - List constructBarChartRodData( - List timeSeriesIntervalGroup, - ) { - int y1 = 0; - int y2 = 0; - int y3 = 0; - int y4 = 0; - for (final e in timeSeriesIntervalGroup) { - y1 += e.totals.ta; - y2 += y1 + e.totals.ga; - y3 += y2 + e.totals.wa; - y4 += y3 + e.totals.un; - } - return [ - BarChartRodData( - toY: y4.toDouble(), - width: 10.toDouble(), - rodStackItems: [ - BarChartRodStackItem(0, y1.toDouble(), UseType.ta.color(context)), - BarChartRodStackItem( - y1.toDouble(), - y2.toDouble(), - UseType.ga.color(context), - ), - BarChartRodStackItem( - y2.toDouble(), - y3.toDouble(), - UseType.wa.color(context), - ), - BarChartRodStackItem( - y3.toDouble(), - y4.toDouble(), - UseType.un.color(context), - ), - ], - borderRadius: BorderRadius.zero, - ), - ]; - } +// List constructBarChartRodData( +// List timeSeriesIntervalGroup, +// ) { +// int y1 = 0; +// int y2 = 0; +// int y3 = 0; +// int y4 = 0; +// for (final e in timeSeriesIntervalGroup) { +// y1 += e.totals.ta; +// y2 += y1 + e.totals.ga; +// y3 += y2 + e.totals.wa; +// y4 += y3 + e.totals.un; +// } +// return [ +// BarChartRodData( +// toY: y4.toDouble(), +// width: 10.toDouble(), +// rodStackItems: [ +// BarChartRodStackItem(0, y1.toDouble(), UseType.ta.color(context)), +// BarChartRodStackItem( +// y1.toDouble(), +// y2.toDouble(), +// UseType.ga.color(context), +// ), +// BarChartRodStackItem( +// y2.toDouble(), +// y3.toDouble(), +// UseType.wa.color(context), +// ), +// BarChartRodStackItem( +// y3.toDouble(), +// y4.toDouble(), +// UseType.un.color(context), +// ), +// ], +// borderRadius: BorderRadius.zero, +// ), +// ]; +// } - // BarTouchData get barTouchData => BarTouchData( - // touchTooltipData: BarTouchTooltipData( - // fitInsideVertically: true, - // tooltipBgColor: Colors.blueGrey, - // getTooltipItem: (group, groupIndex, rod, rodIndex) { - // return BarTooltipItem( - // "groupindex $groupIndex rodIndex $rodIndex", - // const TextStyle( - // color: Colors.white, - // fontWeight: FontWeight.bold, - // fontSize: 18, - // ), - // children: [ - // toolTipText(rod), - // ], - // ); - // }, - // ), - // // touchCallback: (FlTouchEvent event, barTouchResponse) { - // // setState(() { - // // if (!event.isInterestedForInteractions || - // // barTouchResponse == null || - // // barTouchResponse.spot == null) { - // // touchedIndex = -1; - // // return; - // // } - // // touchedIndex = barTouchResponse.spot!.touchedBarGroupIndex; - // // }); - // // }, - // ); +// // BarTouchData get barTouchData => BarTouchData( +// // touchTooltipData: BarTouchTooltipData( +// // fitInsideVertically: true, +// // tooltipBgColor: Colors.blueGrey, +// // getTooltipItem: (group, groupIndex, rod, rodIndex) { +// // return BarTooltipItem( +// // "groupindex $groupIndex rodIndex $rodIndex", +// // const TextStyle( +// // color: Colors.white, +// // fontWeight: FontWeight.bold, +// // fontSize: 18, +// // ), +// // children: [ +// // toolTipText(rod), +// // ], +// // ); +// // }, +// // ), +// // // touchCallback: (FlTouchEvent event, barTouchResponse) { +// // // setState(() { +// // // if (!event.isInterestedForInteractions || +// // // barTouchResponse == null || +// // // barTouchResponse.spot == null) { +// // // touchedIndex = -1; +// // // return; +// // // } +// // // touchedIndex = barTouchResponse.spot!.touchedBarGroupIndex; +// // // }); +// // // }, +// // ); - // TextSpan toolTipText(BarChartRodData rodData) { - // double rodPercentage(int index) { - // return (rodData.rodStackItems[index].toY - - // rodData.rodStackItems[index].fromY) / - // rodData.toY * - // 100; - // } +// // TextSpan toolTipText(BarChartRodData rodData) { +// // double rodPercentage(int index) { +// // return (rodData.rodStackItems[index].toY - +// // rodData.rodStackItems[index].fromY) / +// // rodData.toY * +// // 100; +// // } - // return TextSpan( - // children: [ - // const WidgetSpan( - // child: Icon(Icons.chat_bubble, size: 14), - // ), - // TextSpan( - // text: " ${rodData.toY}", - // ), - // TextSpan( - // text: "/nIT ${rodPercentage(0)}%", - // style: TextStyle(color: UseType.ta.color(context)), - // ), - // TextSpan( - // text: " IGC ${rodPercentage(1)}%", - // style: TextStyle(color: UseType.ga.color(context)), - // ), - // TextSpan( - // text: " Direct ${rodPercentage(2)}%", - // style: TextStyle(color: UseType.wa.color(context)), - // ), - // ], - // ); - // } -} +// // return TextSpan( +// // children: [ +// // const WidgetSpan( +// // child: Icon(Icons.chat_bubble, size: 14), +// // ), +// // TextSpan( +// // text: " ${rodData.toY}", +// // ), +// // TextSpan( +// // text: "/nIT ${rodPercentage(0)}%", +// // style: TextStyle(color: UseType.ta.color(context)), +// // ), +// // TextSpan( +// // text: " IGC ${rodPercentage(1)}%", +// // style: TextStyle(color: UseType.ga.color(context)), +// // ), +// // TextSpan( +// // text: " Direct ${rodPercentage(2)}%", +// // style: TextStyle(color: UseType.wa.color(context)), +// // ), +// // ], +// // ); +// // } +// } diff --git a/lib/pangea/pages/analytics/space_analytics/space_analytics.dart b/lib/pangea/pages/analytics/space_analytics/space_analytics.dart index 50a8cb7c2..3f752bd4a 100644 --- a/lib/pangea/pages/analytics/space_analytics/space_analytics.dart +++ b/lib/pangea/pages/analytics/space_analytics/space_analytics.dart @@ -1,121 +1,114 @@ -import 'dart:async'; -import 'dart:developer'; +// import 'dart:async'; +// import 'dart:developer'; -import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; -import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/models/language_model.dart'; -import 'package:fluffychat/pangea/utils/error_handler.dart'; -import 'package:fluffychat/pangea/widgets/common/list_placeholder.dart'; -import 'package:fluffychat/pangea/widgets/common/p_circular_loader.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:matrix/matrix.dart'; +// import 'package:fluffychat/pangea/constants/pangea_room_types.dart'; +// import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; +// import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; +// import 'package:fluffychat/pangea/models/language_model.dart'; +// import 'package:fluffychat/pangea/utils/error_handler.dart'; +// import 'package:fluffychat/pangea/widgets/common/list_placeholder.dart'; +// import 'package:fluffychat/pangea/widgets/common/p_circular_loader.dart'; +// import 'package:flutter/foundation.dart'; +// import 'package:flutter/material.dart'; +// import 'package:go_router/go_router.dart'; +// import 'package:matrix/matrix.dart'; -import '../../../../widgets/matrix.dart'; -import '../../../utils/sync_status_util_v2.dart'; -import 'space_analytics_view.dart'; +// import '../../../../widgets/matrix.dart'; +// import '../../../utils/sync_status_util_v2.dart'; -class SpaceAnalyticsPage extends StatefulWidget { - final BarChartViewSelection selectedView; - const SpaceAnalyticsPage({super.key, required this.selectedView}); +// class SpaceAnalyticsPage extends StatefulWidget { +// final BarChartViewSelection selectedView; +// const SpaceAnalyticsPage({super.key, required this.selectedView}); - @override - State createState() => SpaceAnalyticsV2Controller(); -} +// @override +// State createState() => SpaceAnalyticsV2Controller(); +// } -class SpaceAnalyticsV2Controller extends State { - bool _initialized = false; - // StreamSubscription? stateSub; - // Timer? refreshTimer; +// class SpaceAnalyticsV2Controller extends State { +// bool _initialized = false; +// // StreamSubscription? stateSub; +// // Timer? refreshTimer; - List chats = []; - List students = []; - String? get spaceId => GoRouterState.of(context).pathParameters['spaceid']; - Room? _spaceRoom; - List targetLanguages = []; +// List chats = []; +// List students = []; +// String? get spaceId => GoRouterState.of(context).pathParameters['spaceid']; +// Room? _spaceRoom; +// List targetLanguages = []; - @override - void initState() { - super.initState(); - Future.delayed(Duration.zero, () async { - if (spaceRoom == null || (!(spaceRoom?.isSpace ?? false))) { - context.go('/rooms'); - } - getChatAndStudents(); - }); - } +// @override +// void initState() { +// super.initState(); +// Future.delayed(Duration.zero, () async { +// if (spaceRoom == null || (!(spaceRoom?.isSpace ?? false))) { +// context.go('/rooms'); +// } +// getChatAndStudents(); +// }); +// } - Room? get spaceRoom { - if (_spaceRoom == null || _spaceRoom!.id != spaceId) { - debugPrint("updating _spaceRoom"); - _spaceRoom = spaceId != null - ? Matrix.of(context).client.getRoomById(spaceId!) - : null; - if (_spaceRoom == null) { - context.go('/rooms/analytics'); - return null; - } - getChatAndStudents().then((_) => setTargetLanguages()); - } - return _spaceRoom; - } +// Room? get spaceRoom { +// if (_spaceRoom == null || _spaceRoom!.id != spaceId) { +// debugPrint("updating _spaceRoom"); +// _spaceRoom = spaceId != null +// ? Matrix.of(context).client.getRoomById(spaceId!) +// : null; +// if (_spaceRoom == null) { +// context.go('/rooms/analytics'); +// return null; +// } +// getChatAndStudents().then((_) => setTargetLanguages()); +// } +// return _spaceRoom; +// } - Future getChatAndStudents() async { - try { - await spaceRoom?.requestParticipants(); +// Future getChatAndStudents() async { +// try { +// await spaceRoom?.requestParticipants(); - if (spaceRoom != null) { - final response = await Matrix.of(context).client.getSpaceHierarchy( - spaceRoom!.id, - ); +// if (spaceRoom != null) { +// final response = await Matrix.of(context).client.getSpaceHierarchy( +// spaceRoom!.id, +// ); - // set the latest fetched full hierarchy in message analytics controller - // we want to avoid calling this endpoint again and again, so whenever the - // data is made available, set it in the controller - MatrixState.pangeaController.analytics - .setLatestHierarchy(_spaceRoom!.id, response); +// students = spaceRoom!.students; +// chats = response.rooms +// .where( +// (room) => +// room.roomId != spaceRoom!.id && +// room.roomType != PangeaRoomTypes.analytics, +// ) +// .toList(); +// chats.sort((a, b) => a.roomType == 'm.space' ? -1 : 1); +// } - students = spaceRoom!.students; - chats = response.rooms - .where( - (room) => - room.roomId != spaceRoom!.id && - room.roomType != PangeaRoomTypes.analytics, - ) - .toList(); - chats.sort((a, b) => a.roomType == 'm.space' ? -1 : 1); - } +// setState(() { +// _initialized = true; +// }); +// } catch (err, s) { +// debugger(when: kDebugMode); +// ErrorHandler.logError(e: err, s: s); +// } +// } - setState(() { - _initialized = true; - }); - } catch (err, s) { - debugger(when: kDebugMode); - ErrorHandler.logError(e: err, s: s); - } - } +// Future setTargetLanguages() async { +// // get a list of language models, sorted by the +// // number of students who are learning that language +// targetLanguages = await spaceRoom?.targetLanguages() ?? []; +// setState(() {}); +// } - Future setTargetLanguages() async { - // get a list of language models, sorted by the - // number of students who are learning that language - targetLanguages = await spaceRoom?.targetLanguages() ?? []; - setState(() {}); - } - - @override - Widget build(BuildContext context) { - if (!_initialized) return const PCircular(); - return PLoadingStatusV2( - // if we everr want it rebuild the whole thing each time (and run initState again) - // but this is computationally expensive! - // key: UniqueKey(), - shimmerChild: const ListPlaceholder(), - // onFinish: () { - // getChatAndStudentAnalytics(context); - // }, - child: SpaceAnalyticsView(this), - ); - } -} +// @override +// Widget build(BuildContext context) { +// if (!_initialized) return const PCircular(); +// return PLoadingStatusV2( +// // if we everr want it rebuild the whole thing each time (and run initState again) +// // but this is computationally expensive! +// // key: UniqueKey(), +// shimmerChild: const ListPlaceholder(), +// // onFinish: () { +// // getChatAndStudentAnalytics(context); +// // }, +// child: SpaceAnalyticsView(this), +// ); +// } +// } diff --git a/lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart b/lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart index c72ec3c26..02c5cb133 100644 --- a/lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart +++ b/lib/pangea/pages/analytics/space_analytics/space_analytics_view.dart @@ -1,66 +1,66 @@ -import 'package:fluffychat/widgets/matrix.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_gen/gen_l10n/l10n.dart'; -import '../base_analytics.dart'; -import 'space_analytics.dart'; +// import '../base_analytics.dart'; +// import 'space_analytics.dart'; -class SpaceAnalyticsView extends StatelessWidget { - final SpaceAnalyticsV2Controller controller; - const SpaceAnalyticsView(this.controller, {super.key}); +// class SpaceAnalyticsView extends StatelessWidget { +// final SpaceAnalyticsV2Controller controller; +// const SpaceAnalyticsView(this.controller, {super.key}); - @override - Widget build(BuildContext context) { - final String pageTitle = L10n.of(context)!.spaceAnalytics; - final TabData tab1 = TabData( - type: AnalyticsEntryType.room, - icon: Icons.chat_bubble_outline, - items: controller.chats - .map( - (room) => TabItem( - avatar: room.avatarUrl, - displayName: room.name ?? - Matrix.of(context) - .client - .getRoomById(room.roomId) - ?.getLocalizedDisplayname() ?? - "", - id: room.roomId, - ), - ) - .toList(), - ); - final TabData tab2 = TabData( - type: AnalyticsEntryType.student, - icon: Icons.people_outline, - items: controller.students - .map( - (s) => TabItem( - avatar: s.avatarUrl, - displayName: s.calcDisplayname(), - id: s.id, - ), - ) - .toList(), - ); +// @override +// Widget build(BuildContext context) { +// final String pageTitle = L10n.of(context)!.spaceAnalytics; +// final TabData tab1 = TabData( +// type: AnalyticsEntryType.room, +// icon: Icons.chat_bubble_outline, +// items: controller.chats +// .map( +// (room) => TabItem( +// avatar: room.avatarUrl, +// displayName: room.name ?? +// Matrix.of(context) +// .client +// .getRoomById(room.roomId) +// ?.getLocalizedDisplayname() ?? +// "", +// id: room.roomId, +// ), +// ) +// .toList(), +// ); +// final TabData tab2 = TabData( +// type: AnalyticsEntryType.student, +// icon: Icons.people_outline, +// items: controller.students +// .map( +// (s) => TabItem( +// avatar: s.avatarUrl, +// displayName: s.calcDisplayname(), +// id: s.id, +// ), +// ) +// .toList(), +// ); - return controller.spaceId != null - ? BaseAnalyticsPage( - selectedView: controller.widget.selectedView, - pageTitle: pageTitle, - tabs: [tab1, tab2], - alwaysSelected: AnalyticsSelected( - controller.spaceId!, - AnalyticsEntryType.space, - controller.spaceRoom?.name ?? "", - ), - defaultSelected: AnalyticsSelected( - controller.spaceId!, - AnalyticsEntryType.space, - controller.spaceRoom?.name ?? "", - ), - targetLanguages: controller.targetLanguages, - ) - : const SizedBox(); - } -} +// return controller.spaceId != null +// ? BaseAnalyticsPage( +// selectedView: controller.widget.selectedView, +// pageTitle: pageTitle, +// tabs: [tab1, tab2], +// alwaysSelected: AnalyticsSelected( +// controller.spaceId!, +// AnalyticsEntryType.space, +// controller.spaceRoom?.name ?? "", +// ), +// defaultSelected: AnalyticsSelected( +// controller.spaceId!, +// AnalyticsEntryType.space, +// controller.spaceRoom?.name ?? "", +// ), +// targetLanguages: controller.targetLanguages, +// ) +// : const SizedBox(); +// } +// } diff --git a/lib/pangea/pages/analytics/space_list/space_list.dart b/lib/pangea/pages/analytics/space_list/space_list.dart index e65bb6152..f9dbe4d31 100644 --- a/lib/pangea/pages/analytics/space_list/space_list.dart +++ b/lib/pangea/pages/analytics/space_list/space_list.dart @@ -1,100 +1,100 @@ -import 'dart:async'; +// import 'dart:async'; -import 'package:fluffychat/pangea/enum/time_span.dart'; -import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/models/language_model.dart'; -import 'package:fluffychat/pangea/pages/analytics/space_list/space_list_view.dart'; -import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; +// import 'package:fluffychat/pangea/enum/time_span.dart'; +// import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; +// import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; +// import 'package:fluffychat/pangea/models/language_model.dart'; +// import 'package:fluffychat/pangea/pages/analytics/space_list/space_list_view.dart'; +// import 'package:flutter/material.dart'; +// import 'package:matrix/matrix.dart'; -import '../../../../widgets/matrix.dart'; -import '../../../controllers/pangea_controller.dart'; -import '../../../utils/sync_status_util_v2.dart'; -import '../../../widgets/common/list_placeholder.dart'; +// import '../../../../widgets/matrix.dart'; +// import '../../../controllers/pangea_controller.dart'; +// import '../../../utils/sync_status_util_v2.dart'; +// import '../../../widgets/common/list_placeholder.dart'; -class AnalyticsSpaceList extends StatefulWidget { - const AnalyticsSpaceList({super.key}); +// class AnalyticsSpaceList extends StatefulWidget { +// const AnalyticsSpaceList({super.key}); - @override - State createState() => AnalyticsSpaceListController(); -} +// @override +// State createState() => AnalyticsSpaceListController(); +// } -class AnalyticsSpaceListController extends State { - PangeaController pangeaController = MatrixState.pangeaController; - List spaces = []; - StreamSubscription? stateSub; - List targetLanguages = []; +// class AnalyticsSpaceListController extends State { +// PangeaController pangeaController = MatrixState.pangeaController; +// List spaces = []; +// StreamSubscription? stateSub; +// List targetLanguages = []; - @override - void initState() { - super.initState(); - setSpaceList().then((_) => setTargetLanguages()); +// @override +// void initState() { +// super.initState(); +// setSpaceList().then((_) => setTargetLanguages()); - // reload dropdowns when their values change in analytics page - stateSub = pangeaController.analytics.stateStream.listen( - (_) => setState(() {}), - ); - } +// // reload dropdowns when their values change in analytics page +// stateSub = pangeaController.analytics.stateStream.listen( +// (_) => setState(() {}), +// ); +// } - @override - void dispose() { - stateSub?.cancel(); - super.dispose(); - } +// @override +// void dispose() { +// stateSub?.cancel(); +// super.dispose(); +// } - StreamController refreshStream = StreamController.broadcast(); +// StreamController refreshStream = StreamController.broadcast(); - Future setSpaceList() async { - final spaceList = await Matrix.of(context).client.spacesImTeaching; - spaces = spaceList - .where( - (space) => !spaceList.any( - (parentSpace) => parentSpace.spaceChildren - .any((child) => child.roomId == space.id), - ), - ) - .toList(); - setState(() {}); - } +// Future setSpaceList() async { +// final spaceList = Matrix.of(context).client.spacesImTeaching; +// spaces = spaceList +// .where( +// (space) => !spaceList.any( +// (parentSpace) => parentSpace.spaceChildren +// .any((child) => child.roomId == space.id), +// ), +// ) +// .toList(); +// setState(() {}); +// } - Future setTargetLanguages() async { - if (spaces.isEmpty) return; - final Map langCounts = {}; - for (final Room space in spaces) { - final List targetLangs = await space.targetLanguages(); - for (final LanguageModel lang in targetLangs) { - langCounts[lang] ??= 0; - langCounts[lang] = langCounts[lang]! + 1; - } - } - targetLanguages = langCounts.entries.map((entry) => entry.key).toList() - ..sort( - (a, b) => langCounts[b]!.compareTo(langCounts[a]!), - ); - setState(() {}); - } +// Future setTargetLanguages() async { +// if (spaces.isEmpty) return; +// final Map langCounts = {}; +// for (final Room space in spaces) { +// final List targetLangs = await space.targetLanguages(); +// for (final LanguageModel lang in targetLangs) { +// langCounts[lang] ??= 0; +// langCounts[lang] = langCounts[lang]! + 1; +// } +// } +// targetLanguages = langCounts.entries.map((entry) => entry.key).toList() +// ..sort( +// (a, b) => langCounts[b]!.compareTo(langCounts[a]!), +// ); +// setState(() {}); +// } - void toggleTimeSpan(BuildContext context, TimeSpan timeSpan) { - pangeaController.analytics.setCurrentAnalyticsTimeSpan(timeSpan); - refreshStream.add(false); - setState(() {}); - } +// void toggleTimeSpan(BuildContext context, TimeSpan timeSpan) { +// pangeaController.analytics.setCurrentAnalyticsTimeSpan(timeSpan); +// refreshStream.add(false); +// setState(() {}); +// } - Future toggleSpaceLang(LanguageModel lang) async { - await pangeaController.analytics.setCurrentAnalyticsLang(lang); - refreshStream.add(false); - setState(() {}); - } +// Future toggleSpaceLang(LanguageModel lang) async { +// await pangeaController.analytics.setCurrentAnalyticsLang(lang); +// refreshStream.add(false); +// setState(() {}); +// } - @override - Widget build(BuildContext context) { - return PLoadingStatusV2( - shimmerChild: const ListPlaceholder(), - child: AnalyticsSpaceListView(this), - onFinish: () { - // getAllClassAnalytics(context); - }, - ); - } -} +// @override +// Widget build(BuildContext context) { +// return PLoadingStatusV2( +// shimmerChild: const ListPlaceholder(), +// child: AnalyticsSpaceListView(this), +// onFinish: () { +// // getAllClassAnalytics(context); +// }, +// ); +// } +// } diff --git a/lib/pangea/pages/analytics/space_list/space_list_view.dart b/lib/pangea/pages/analytics/space_list/space_list_view.dart index 7ef5fb45e..c9b63a62c 100644 --- a/lib/pangea/pages/analytics/space_list/space_list_view.dart +++ b/lib/pangea/pages/analytics/space_list/space_list_view.dart @@ -1,89 +1,89 @@ -import 'package:fluffychat/pangea/enum/time_span.dart'; -import 'package:fluffychat/pangea/pages/analytics/analytics_language_button.dart'; -import 'package:fluffychat/pangea/pages/analytics/analytics_list_tile.dart'; -import 'package:fluffychat/pangea/pages/analytics/time_span_menu_button.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; +// import 'package:fluffychat/pangea/enum/time_span.dart'; +// import 'package:fluffychat/pangea/pages/analytics/analytics_language_button.dart'; +// import 'package:fluffychat/pangea/pages/analytics/analytics_list_tile.dart'; +// import 'package:fluffychat/pangea/pages/analytics/time_span_menu_button.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_gen/gen_l10n/l10n.dart'; +// import 'package:go_router/go_router.dart'; -import '../base_analytics.dart'; -import 'space_list.dart'; +// import '../base_analytics.dart'; +// import 'space_list.dart'; -class AnalyticsSpaceListView extends StatelessWidget { - final AnalyticsSpaceListController controller; - const AnalyticsSpaceListView(this.controller, {super.key}); +// class AnalyticsSpaceListView extends StatelessWidget { +// final AnalyticsSpaceListController controller; +// const AnalyticsSpaceListView(this.controller, {super.key}); - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - centerTitle: true, - title: Text( - L10n.of(context)!.spaceAnalytics, - style: TextStyle( - color: Theme.of(context).textTheme.bodyLarge!.color, - fontSize: 18, - fontWeight: FontWeight.w700, - ), - overflow: TextOverflow.clip, - textAlign: TextAlign.center, - ), - leading: IconButton( - icon: const Icon(Icons.close_outlined), - onPressed: () => context.pop(), - ), - ), - body: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - TimeSpanMenuButton( - value: controller - .pangeaController.analytics.currentAnalyticsTimeSpan, - onChange: (TimeSpan value) => controller.toggleTimeSpan( - context, - value, - ), - ), - AnalyticsLanguageButton( - value: - controller.pangeaController.analytics.currentAnalyticsLang, - onChange: (lang) => controller.toggleSpaceLang(lang), - languages: - controller.pangeaController.pLanguageStore.targetOptions, - ), - ], - ), - Flexible( - child: ListView.builder( - itemCount: controller.spaces.length, - itemBuilder: (context, i) => AnalyticsListTile( - defaultSelected: AnalyticsSelected( - controller.spaces[i].id, - AnalyticsEntryType.space, - controller.spaces[i].name, - ), - avatar: controller.spaces[i].avatar, - selected: AnalyticsSelected( - controller.spaces[i].id, - AnalyticsEntryType.space, - controller.spaces[i].name, - ), - onTap: (selected) { - context.go( - '/rooms/analytics/${selected.id}', - ); - }, - allowNavigateOnSelect: true, - isSelected: false, - pangeaController: controller.pangeaController, - refreshStream: controller.refreshStream, - ), - ), - ), - ], - ), - ); - } -} +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// appBar: AppBar( +// centerTitle: true, +// title: Text( +// L10n.of(context)!.spaceAnalytics, +// style: TextStyle( +// color: Theme.of(context).textTheme.bodyLarge!.color, +// fontSize: 18, +// fontWeight: FontWeight.w700, +// ), +// overflow: TextOverflow.clip, +// textAlign: TextAlign.center, +// ), +// leading: IconButton( +// icon: const Icon(Icons.close_outlined), +// onPressed: () => context.pop(), +// ), +// ), +// body: Column( +// children: [ +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceEvenly, +// children: [ +// TimeSpanMenuButton( +// value: controller +// .pangeaController.analytics.currentAnalyticsTimeSpan, +// onChange: (TimeSpan value) => controller.toggleTimeSpan( +// context, +// value, +// ), +// ), +// AnalyticsLanguageButton( +// value: +// controller.pangeaController.analytics.currentAnalyticsLang, +// onChange: (lang) => controller.toggleSpaceLang(lang), +// languages: +// controller.pangeaController.pLanguageStore.targetOptions, +// ), +// ], +// ), +// Flexible( +// child: ListView.builder( +// itemCount: controller.spaces.length, +// itemBuilder: (context, i) => AnalyticsListTile( +// defaultSelected: AnalyticsSelected( +// controller.spaces[i].id, +// AnalyticsEntryType.space, +// controller.spaces[i].name, +// ), +// avatar: controller.spaces[i].avatar, +// selected: AnalyticsSelected( +// controller.spaces[i].id, +// AnalyticsEntryType.space, +// controller.spaces[i].name, +// ), +// onTap: (selected) { +// context.go( +// '/rooms/analytics/${selected.id}', +// ); +// }, +// allowNavigateOnSelect: true, +// isSelected: false, +// pangeaController: controller.pangeaController, +// refreshStream: controller.refreshStream, +// ), +// ), +// ), +// ], +// ), +// ); +// } +// } diff --git a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart index 007a04d93..3a5309e5e 100644 --- a/lib/pangea/pages/analytics/student_analytics/student_analytics.dart +++ b/lib/pangea/pages/analytics/student_analytics/student_analytics.dart @@ -1,90 +1,90 @@ -import 'dart:developer'; +// import 'dart:developer'; -import 'package:fluffychat/pangea/constants/language_constants.dart'; -import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; -import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; -import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/models/language_model.dart'; -import 'package:fluffychat/pangea/widgets/common/list_placeholder.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; +// import 'package:fluffychat/pangea/constants/language_constants.dart'; +// import 'package:fluffychat/pangea/controllers/language_list_controller.dart'; +// import 'package:fluffychat/pangea/enum/bar_chart_view_enum.dart'; +// import 'package:fluffychat/pangea/extensions/client_extension/client_extension.dart'; +// import 'package:fluffychat/pangea/extensions/pangea_room_extension/pangea_room_extension.dart'; +// import 'package:fluffychat/pangea/models/language_model.dart'; +// import 'package:fluffychat/pangea/widgets/common/list_placeholder.dart'; +// import 'package:flutter/foundation.dart'; +// import 'package:flutter/material.dart'; +// import 'package:matrix/matrix.dart'; -import '../../../../widgets/matrix.dart'; -import '../../../controllers/pangea_controller.dart'; -import '../../../utils/sync_status_util_v2.dart'; -import '../base_analytics.dart'; -import 'student_analytics_view.dart'; +// import '../../../../widgets/matrix.dart'; +// import '../../../controllers/pangea_controller.dart'; +// import '../../../utils/sync_status_util_v2.dart'; +// import '../base_analytics.dart'; +// import 'student_analytics_view.dart'; -class StudentAnalyticsPage extends StatefulWidget { - final BarChartViewSelection selectedView; - const StudentAnalyticsPage({super.key, required this.selectedView}); +// class StudentAnalyticsPage extends StatefulWidget { +// final BarChartViewSelection selectedView; +// const StudentAnalyticsPage({super.key, required this.selectedView}); - @override - State createState() => StudentAnalyticsController(); -} +// @override +// State createState() => StudentAnalyticsController(); +// } -class StudentAnalyticsController extends State { - final PangeaController _pangeaController = MatrixState.pangeaController; - AnalyticsSelected? selected; +// class StudentAnalyticsController extends State { +// final PangeaController _pangeaController = MatrixState.pangeaController; +// AnalyticsSelected? selected; - @override - void initState() { - super.initState(); - } +// @override +// void initState() { +// super.initState(); +// } - @override - void dispose() { - super.dispose(); - } +// @override +// void dispose() { +// super.dispose(); +// } - List _chats = []; - List get chats { - if (_chats.isEmpty) { - _pangeaController.matrixState.client.chatsImAStudentIn.then((result) { - setState(() => _chats = result); - }); - } - return _chats; - } +// List _chats = []; +// List get chats { +// if (_chats.isEmpty) { +// _pangeaController.matrixState.client.chatsImAStudentIn.then((result) { +// setState(() => _chats = result); +// }); +// } +// return _chats; +// } - List get spaces => - _pangeaController.matrixState.client.spacesImAStudentIn; +// List get spaces => +// _pangeaController.matrixState.client.spacesImAStudentIn; - String? get userId { - final id = _pangeaController.matrixState.client.userID; - debugger(when: kDebugMode && id == null); - return id; - } +// String? get userId { +// final id = _pangeaController.matrixState.client.userID; +// debugger(when: kDebugMode && id == null); +// return id; +// } - List get targetLanguages { - final LanguageModel? l2 = - _pangeaController.languageController.activeL2Model(); - final List analyticsRoomLangs = - _pangeaController.matrixState.client.allMyAnalyticsRooms - .map((analyticsRoom) => analyticsRoom.madeForLang) - .where((langCode) => langCode != null) - .map((langCode) => PangeaLanguage.byLangCode(langCode!)) - .where( - (langModel) => langModel.langCode != LanguageKeys.unknownLanguage, - ) - .toList(); - if (l2 != null) { - analyticsRoomLangs.add(l2); - } - return analyticsRoomLangs.toSet().toList(); - } +// List get targetLanguages { +// final LanguageModel? l2 = +// _pangeaController.languageController.activeL2Model(); +// final List analyticsRoomLangs = +// _pangeaController.matrixState.client.allMyAnalyticsRooms +// .map((analyticsRoom) => analyticsRoom.madeForLang) +// .where((langCode) => langCode != null) +// .map((langCode) => PangeaLanguage.byLangCode(langCode!)) +// .where( +// (langModel) => langModel.langCode != LanguageKeys.unknownLanguage, +// ) +// .toList(); +// if (l2 != null) { +// analyticsRoomLangs.add(l2); +// } +// return analyticsRoomLangs.toSet().toList(); +// } - @override - Widget build(BuildContext context) { - return PLoadingStatusV2( - // if we everr want it rebuild the whole thing each time (and run initState again) - // but this is computationally expensive! - // key: UniqueKey(), - shimmerChild: const ListPlaceholder(), - // onFinish: initialize, - child: StudentAnalyticsView(this), - ); - } -} +// @override +// Widget build(BuildContext context) { +// return PLoadingStatusV2( +// // if we everr want it rebuild the whole thing each time (and run initState again) +// // but this is computationally expensive! +// // key: UniqueKey(), +// shimmerChild: const ListPlaceholder(), +// // onFinish: initialize, +// child: StudentAnalyticsView(this), +// ); +// } +// } diff --git a/lib/pangea/pages/analytics/student_analytics/student_analytics_view.dart b/lib/pangea/pages/analytics/student_analytics/student_analytics_view.dart index 6ea754891..a778f35d8 100644 --- a/lib/pangea/pages/analytics/student_analytics/student_analytics_view.dart +++ b/lib/pangea/pages/analytics/student_analytics/student_analytics_view.dart @@ -1,66 +1,66 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_gen/gen_l10n/l10n.dart'; -import '../../../../utils/matrix_sdk_extensions/matrix_locals.dart'; -import '../base_analytics.dart'; -import 'student_analytics.dart'; +// import '../../../../utils/matrix_sdk_extensions/matrix_locals.dart'; +// import '../base_analytics.dart'; +// import 'student_analytics.dart'; -class StudentAnalyticsView extends StatelessWidget { - final StudentAnalyticsController controller; - const StudentAnalyticsView(this.controller, {super.key}); +// class StudentAnalyticsView extends StatelessWidget { +// final StudentAnalyticsController controller; +// const StudentAnalyticsView(this.controller, {super.key}); - @override - Widget build(BuildContext context) { - final String pageTitle = L10n.of(context)!.myLearning; - final TabData chatTabData = TabData( - type: AnalyticsEntryType.room, - icon: Icons.chat_bubble_outline, - items: (controller.chats) - .map( - (c) => TabItem( - avatar: c.avatar, - displayName: - c.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), - id: c.id, - ), - ) - .toList(), - allowNavigateOnSelect: false, - ); - final TabData classTabData = TabData( - type: AnalyticsEntryType.space, - icon: Icons.workspaces, - items: (controller.spaces ?? []) - .map( - (c) => TabItem( - avatar: c.avatar, - displayName: - c.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), - id: c.id, - ), - ) - .toList(), - allowNavigateOnSelect: false, - ); +// @override +// Widget build(BuildContext context) { +// final String pageTitle = L10n.of(context)!.myLearning; +// final TabData chatTabData = TabData( +// type: AnalyticsEntryType.room, +// icon: Icons.chat_bubble_outline, +// items: (controller.chats) +// .map( +// (c) => TabItem( +// avatar: c.avatar, +// displayName: +// c.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), +// id: c.id, +// ), +// ) +// .toList(), +// allowNavigateOnSelect: false, +// ); +// final TabData classTabData = TabData( +// type: AnalyticsEntryType.space, +// icon: Icons.workspaces, +// items: (controller.spaces ?? []) +// .map( +// (c) => TabItem( +// avatar: c.avatar, +// displayName: +// c.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), +// id: c.id, +// ), +// ) +// .toList(), +// allowNavigateOnSelect: false, +// ); - return controller.userId != null - ? BaseAnalyticsPage( - selectedView: controller.widget.selectedView, - pageTitle: pageTitle, - tabs: [chatTabData, classTabData], - alwaysSelected: AnalyticsSelected( - controller.userId!, - AnalyticsEntryType.student, - L10n.of(context)!.allChatsAndClasses, - ), - myAnalyticsController: controller, - defaultSelected: AnalyticsSelected( - controller.userId!, - AnalyticsEntryType.student, - L10n.of(context)!.allChatsAndClasses, - ), - targetLanguages: controller.targetLanguages, - ) - : const SizedBox(); - } -} +// return controller.userId != null +// ? BaseAnalyticsPage( +// selectedView: controller.widget.selectedView, +// pageTitle: pageTitle, +// tabs: [chatTabData, classTabData], +// alwaysSelected: AnalyticsSelected( +// controller.userId!, +// AnalyticsEntryType.student, +// L10n.of(context)!.allChatsAndClasses, +// ), +// myAnalyticsController: controller, +// defaultSelected: AnalyticsSelected( +// controller.userId!, +// AnalyticsEntryType.student, +// L10n.of(context)!.allChatsAndClasses, +// ), +// targetLanguages: controller.targetLanguages, +// ) +// : const SizedBox(); +// } +// } diff --git a/lib/pangea/pages/class_invitation_selection/class_invitation_selection.dart b/lib/pangea/pages/class_invitation_selection/class_invitation_selection.dart index 0164f7b84..8289d357f 100644 --- a/lib/pangea/pages/class_invitation_selection/class_invitation_selection.dart +++ b/lib/pangea/pages/class_invitation_selection/class_invitation_selection.dart @@ -53,7 +53,10 @@ class ClassInvitationSelectionController if (success.error == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text(L10n.of(context)!.contactHasBeenInvitedToTheGroup), + // #Pangea + // content: Text(L10n.of(context)!.contactHasBeenInvitedToTheGroup), + content: Text(L10n.of(context)!.contactHasBeenInvitedToTheChat), + // Pangea# ), ); } diff --git a/lib/pangea/utils/logout.dart b/lib/pangea/utils/logout.dart index aa4441e13..6c57754ef 100644 --- a/lib/pangea/utils/logout.dart +++ b/lib/pangea/utils/logout.dart @@ -1,11 +1,9 @@ -import 'package:flutter/material.dart'; - import 'package:adaptive_dialog/adaptive_dialog.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; -import 'package:fluffychat/widgets/matrix.dart'; - void pLogoutAction(BuildContext context, {bool? isDestructiveAction}) async { if (await showOkCancelAlertDialog( useRootNavigator: false, @@ -20,6 +18,10 @@ void pLogoutAction(BuildContext context, {bool? isDestructiveAction}) async { return; } final matrix = Matrix.of(context); + + // before wiping out locally cached construct data, save it to the server + await MatrixState.pangeaController.myAnalytics.updateAnalytics(); + await showFutureLoadingDialog( context: context, future: () => matrix.client.logout(), diff --git a/lib/pangea/utils/overlay.dart b/lib/pangea/utils/overlay.dart index c83c39af4..c49b1250e 100644 --- a/lib/pangea/utils/overlay.dart +++ b/lib/pangea/utils/overlay.dart @@ -1,5 +1,6 @@ import 'dart:developer'; import 'dart:math'; +import 'dart:ui'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/utils/any_state_holder.dart'; @@ -229,10 +230,13 @@ class TransparentBackdrop extends StatelessWidget { } MatrixState.pAnyState.closeOverlay(); }, - child: Container( - height: double.infinity, - width: double.infinity, - color: Colors.transparent, + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 2.5, sigmaY: 2.5), + child: Container( + height: double.infinity, + width: double.infinity, + color: Colors.transparent, + ), ), ), ); diff --git a/lib/pangea/widgets/animations/gain_points.dart b/lib/pangea/widgets/animations/gain_points.dart new file mode 100644 index 000000000..13ae324e7 --- /dev/null +++ b/lib/pangea/widgets/animations/gain_points.dart @@ -0,0 +1,110 @@ +import 'dart:async'; + +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; +import 'package:fluffychat/pangea/utils/bot_style.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/material.dart'; + +class PointsGainedAnimation extends StatefulWidget { + final Color? gainColor; + final Color? loseColor; + const PointsGainedAnimation({ + super.key, + this.gainColor, + this.loseColor = Colors.red, + }); + + @override + PointsGainedAnimationState createState() => PointsGainedAnimationState(); +} + +class PointsGainedAnimationState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation _offsetAnimation; + late Animation _fadeAnimation; + + StreamSubscription? _pointsSubscription; + int? get _prevXP => MatrixState.pangeaController.analytics.prevXP; + int? get _currentXP => MatrixState.pangeaController.analytics.currentXP; + int? _addedPoints; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: const Duration(seconds: 2), + vsync: this, + ); + + _offsetAnimation = Tween( + begin: const Offset(0.0, 0.0), + end: const Offset(0.0, -1.0), + ).animate( + CurvedAnimation( + parent: _controller, + curve: Curves.easeOut, + ), + ); + + _fadeAnimation = Tween( + begin: 1.0, + end: 0.0, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Curves.easeOut, + ), + ); + + _pointsSubscription = MatrixState + .pangeaController.analytics.analyticsStream.stream + .listen(_showPointsGained); + } + + @override + void dispose() { + _controller.dispose(); + _pointsSubscription?.cancel(); + super.dispose(); + } + + void _showPointsGained(List constructs) { + setState(() => _addedPoints = (_currentXP ?? 0) - (_prevXP ?? 0)); + if (_prevXP != _currentXP) { + _controller.reset(); + _controller.forward(); + } + } + + bool get animate => + _currentXP != null && + _prevXP != null && + _addedPoints != null && + _prevXP! != _currentXP!; + + @override + Widget build(BuildContext context) { + if (!animate) return const SizedBox(); + + final textColor = _addedPoints! > 0 ? widget.gainColor : widget.loseColor; + + return SlideTransition( + position: _offsetAnimation, + child: FadeTransition( + opacity: _fadeAnimation, + child: Text( + '${_addedPoints! > 0 ? '+' : ''}$_addedPoints', + style: BotStyle.text( + context, + big: true, + setColor: textColor == null, + existingStyle: TextStyle( + color: textColor, + ), + ), + ), + ), + ); + } +} diff --git a/lib/pangea/widgets/animations/progress_bar/animated_level_dart.dart b/lib/pangea/widgets/animations/progress_bar/animated_level_dart.dart new file mode 100644 index 000000000..adbc32e33 --- /dev/null +++ b/lib/pangea/widgets/animations/progress_bar/animated_level_dart.dart @@ -0,0 +1,87 @@ +import 'package:fluffychat/config/themes.dart'; +import 'package:flutter/material.dart'; + +class AnimatedLevelBar extends StatefulWidget { + final double height; + final double beginWidth; + final double endWidth; + final BoxDecoration? decoration; + + const AnimatedLevelBar({ + super.key, + required this.height, + required this.beginWidth, + required this.endWidth, + this.decoration, + }); + + @override + AnimatedLevelBarState createState() => AnimatedLevelBarState(); +} + +class AnimatedLevelBarState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + + /// Whether the animation has run for the first time during initState. Don't + /// want the animation to run when the widget mounts, only when points are gained. + bool _init = true; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: FluffyThemes.animationDuration, + ); + + _controller.forward().then((_) => _init = false); + } + + @override + void didUpdateWidget(covariant AnimatedLevelBar oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.endWidth != widget.endWidth) { + _controller.reset(); + _controller.forward(); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + Animation get _animation { + // If this is the first run of the animation, don't animate. This is just the widget mounting, + // not a points gain. This could instead be 'if going from 0 to a non-zero value', but that + // would remove the animation for first points gained. It would remove the need for a flag though. + if (_init) { + return Tween( + begin: widget.endWidth, + end: widget.endWidth, + ).animate(_controller); + } + + // animate the width of the bar + return Tween( + begin: widget.beginWidth, + end: widget.endWidth, + ).animate(_controller); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: _animation, + builder: (context, child) { + return Container( + height: widget.height, + width: _animation.value, + decoration: widget.decoration, + ); + }, + ); + } +} diff --git a/lib/pangea/widgets/animations/progress_bar/level_bar.dart b/lib/pangea/widgets/animations/progress_bar/level_bar.dart new file mode 100644 index 000000000..fb57a3bd5 --- /dev/null +++ b/lib/pangea/widgets/animations/progress_bar/level_bar.dart @@ -0,0 +1,59 @@ +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/constants/analytics_constants.dart'; +import 'package:fluffychat/pangea/widgets/animations/progress_bar/animated_level_dart.dart'; +import 'package:fluffychat/pangea/widgets/animations/progress_bar/progress_bar_details.dart'; +import 'package:flutter/material.dart'; + +class LevelBar extends StatefulWidget { + final LevelBarDetails details; + final ProgressBarDetails progressBarDetails; + + const LevelBar({ + super.key, + required this.details, + required this.progressBarDetails, + }); + + @override + LevelBarState createState() => LevelBarState(); +} + +class LevelBarState extends State { + double prevWidth = 0; + + double get width { + const perLevel = AnalyticsConstants.xpPerLevel; + final percent = (widget.details.currentPoints % perLevel) / perLevel; + return widget.progressBarDetails.totalWidth * percent; + } + + @override + void didUpdateWidget(covariant LevelBar oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.details.currentPoints != widget.details.currentPoints) { + setState(() => prevWidth = width); + } + } + + @override + Widget build(BuildContext context) { + return AnimatedLevelBar( + height: widget.progressBarDetails.height, + beginWidth: prevWidth, + endWidth: width, + decoration: BoxDecoration( + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + color: widget.details.fillColor, + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + blurRadius: 5, + offset: const Offset(5, 0), + ), + ], + ), + ); + } +} diff --git a/lib/pangea/widgets/animations/progress_bar/progress_bar.dart b/lib/pangea/widgets/animations/progress_bar/progress_bar.dart new file mode 100644 index 000000000..ea0263a3c --- /dev/null +++ b/lib/pangea/widgets/animations/progress_bar/progress_bar.dart @@ -0,0 +1,36 @@ +import 'package:fluffychat/pangea/widgets/animations/progress_bar/level_bar.dart'; +import 'package:fluffychat/pangea/widgets/animations/progress_bar/progress_bar_background.dart'; +import 'package:fluffychat/pangea/widgets/animations/progress_bar/progress_bar_details.dart'; +import 'package:flutter/material.dart'; + +// Provide an order list of level indicators, each with it's color +// and stream. Also provide an overall width and pointsPerLevel. + +class ProgressBar extends StatelessWidget { + final List levelBars; + final ProgressBarDetails progressBarDetails; + + const ProgressBar({ + super.key, + required this.levelBars, + required this.progressBarDetails, + }); + + @override + Widget build(BuildContext context) { + return Stack( + alignment: Alignment.centerLeft, + children: [ + ProgressBarBackground(details: progressBarDetails), + for (final levelBar in levelBars) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: LevelBar( + details: levelBar, + progressBarDetails: progressBarDetails, + ), + ), + ], + ); + } +} diff --git a/lib/pangea/widgets/animations/progress_bar/progress_bar_background.dart b/lib/pangea/widgets/animations/progress_bar/progress_bar_background.dart new file mode 100644 index 000000000..1ebfe145d --- /dev/null +++ b/lib/pangea/widgets/animations/progress_bar/progress_bar_background.dart @@ -0,0 +1,30 @@ +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/widgets/animations/progress_bar/progress_bar_details.dart'; +import 'package:flutter/material.dart'; + +class ProgressBarBackground extends StatelessWidget { + final ProgressBarDetails details; + + const ProgressBarBackground({ + super.key, + required this.details, + }); + + @override + Widget build(BuildContext context) { + return Container( + height: details.height + 4, + width: details.totalWidth + 4, + decoration: BoxDecoration( + border: Border.all( + color: details.borderColor.withOpacity(0.5), + width: 2, + ), + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + color: details.borderColor.withOpacity(0.2), + ), + ); + } +} diff --git a/lib/pangea/widgets/animations/progress_bar/progress_bar_details.dart b/lib/pangea/widgets/animations/progress_bar/progress_bar_details.dart new file mode 100644 index 000000000..debe93816 --- /dev/null +++ b/lib/pangea/widgets/animations/progress_bar/progress_bar_details.dart @@ -0,0 +1,23 @@ +import 'dart:ui'; + +class LevelBarDetails { + final Color fillColor; + final int currentPoints; + + const LevelBarDetails({ + required this.fillColor, + required this.currentPoints, + }); +} + +class ProgressBarDetails { + final double totalWidth; + final Color borderColor; + final double height; + + const ProgressBarDetails({ + required this.totalWidth, + required this.borderColor, + this.height = 16, + }); +} diff --git a/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart new file mode 100644 index 000000000..5378796af --- /dev/null +++ b/lib/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart @@ -0,0 +1,74 @@ +import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/construct_list_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class AnalyticsPopup extends StatelessWidget { + final ProgressIndicatorEnum indicator; + final ConstructListModel constructsModel; + + const AnalyticsPopup({ + required this.indicator, + required this.constructsModel, + super.key, + }); + + @override + Widget build(BuildContext context) { + return Dialog( + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 400, + maxHeight: 600, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(20.0), + child: Scaffold( + appBar: AppBar( + title: Text(indicator.tooltip(context)), + leading: IconButton( + icon: const Icon(Icons.close), + onPressed: Navigator.of(context).pop, + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: constructsModel.constructs.isEmpty + ? Center( + child: Text(L10n.of(context)!.noDataFound), + ) + : ListView.builder( + itemCount: constructsModel.constructs.length, + itemBuilder: (context, index) { + return Tooltip( + message: + "${constructsModel.constructs[index].points} / ${constructsModel.type.maxXPPerLemma}", + child: ListTile( + onTap: () {}, + title: Text( + constructsModel.constructs[index].lemma, + ), + subtitle: LinearProgressIndicator( + value: constructsModel.constructs[index].points / + constructsModel.type.maxXPPerLemma, + minHeight: 20, + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + color: indicator.color(context), + ), + contentPadding: + const EdgeInsets.symmetric(horizontal: 20), + ), + ); + }, + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart b/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart new file mode 100644 index 000000000..eb0b0cb62 --- /dev/null +++ b/lib/pangea/widgets/chat_list/analytics_summary/learning_progress_indicators.dart @@ -0,0 +1,259 @@ +import 'dart:async'; + +import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/pangea/constants/analytics_constants.dart'; +import 'package:fluffychat/pangea/controllers/pangea_controller.dart'; +import 'package:fluffychat/pangea/enum/construct_type_enum.dart'; +import 'package:fluffychat/pangea/enum/progress_indicators_enum.dart'; +import 'package:fluffychat/pangea/models/analytics/construct_list_model.dart'; +import 'package:fluffychat/pangea/models/analytics/constructs_model.dart'; +import 'package:fluffychat/pangea/widgets/animations/progress_bar/progress_bar.dart'; +import 'package:fluffychat/pangea/widgets/animations/progress_bar/progress_bar_details.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/analytics_popup.dart'; +import 'package:fluffychat/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart'; +import 'package:fluffychat/widgets/avatar.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:matrix/matrix.dart'; + +/// A summary of "My Analytics" shown at the top of the chat list +/// It shows a variety of progress indicators such as +/// messages sent, words used, and error types, which can +/// be clicked to access more fine-grained analytics data. +class LearningProgressIndicators extends StatefulWidget { + const LearningProgressIndicators({ + super.key, + }); + + @override + LearningProgressIndicatorsState createState() => + LearningProgressIndicatorsState(); +} + +class LearningProgressIndicatorsState + extends State { + final PangeaController _pangeaController = MatrixState.pangeaController; + + /// A stream subscription to listen for updates to + /// the analytics data, either locally or from events + StreamSubscription>? _analyticsUpdateSubscription; + + /// Vocabulary constructs model + ConstructListModel? words; + + /// Morph constructs model + ConstructListModel? morphs; + + bool loading = true; + + // Some buggy stuff is happening with this data not being updated at login, so switching + // to stateful variables for now. Will switch this back later when I have more time to + // figure out why it's now working. + // int get serverXP => _pangeaController.analytics.serverXP; + // int get totalXP => _pangeaController.analytics.currentXP; + // int get level => _pangeaController.analytics.level; + List currentConstructs = []; + int get currentXP => _pangeaController.analytics.calcXP(currentConstructs); + int get localXP => _pangeaController.analytics.calcXP( + _pangeaController.analytics.locallyCachedConstructs, + ); + int get serverXP => currentXP - localXP; + int get level => currentXP ~/ AnalyticsConstants.xpPerLevel; + + @override + void initState() { + super.initState(); + updateAnalyticsData( + _pangeaController.analytics.analyticsStream.value ?? [], + ); + _analyticsUpdateSubscription = _pangeaController + .analytics.analyticsStream.stream + .listen(updateAnalyticsData); + } + + @override + void dispose() { + _analyticsUpdateSubscription?.cancel(); + super.dispose(); + } + + /// Update the analytics data shown in the UI. This comes from a + /// combination of stored events and locally cached data. + Future updateAnalyticsData(List constructs) async { + words = ConstructListModel( + type: ConstructTypeEnum.vocab, + uses: constructs, + ); + morphs = ConstructListModel( + type: ConstructTypeEnum.morph, + uses: constructs, + ); + + currentConstructs = constructs; + if (loading) loading = false; + if (mounted) setState(() {}); + } + + /// Get the number of points for a given progress indicator + ConstructListModel? getConstructsModel(ProgressIndicatorEnum indicator) { + switch (indicator) { + case ProgressIndicatorEnum.wordsUsed: + return words; + case ProgressIndicatorEnum.morphsUsed: + return morphs; + default: + return null; + } + } + + /// Get the number of points for a given progress indicator + int? getProgressPoints(ProgressIndicatorEnum indicator) { + switch (indicator) { + case ProgressIndicatorEnum.wordsUsed: + return words?.lemmas.length; + case ProgressIndicatorEnum.morphsUsed: + return morphs?.lemmas.length; + case ProgressIndicatorEnum.level: + return level; + } + } + + double get levelBarWidth => FluffyThemes.columnWidth - (32 * 2) - 25; + + Color levelColor(int level) { + final colors = [ + const Color.fromARGB(255, 33, 97, 140), // Dark blue + const Color.fromARGB(255, 186, 104, 200), // Soft purple + const Color.fromARGB(255, 123, 31, 162), // Deep purple + const Color.fromARGB(255, 0, 150, 136), // Teal + const Color.fromARGB(255, 247, 143, 143), // Light pink + const Color.fromARGB(255, 220, 20, 60), // Crimson red + ]; + return colors[level % colors.length]; + } + + @override + Widget build(BuildContext context) { + if (Matrix.of(context).client.userID == null) { + return const SizedBox(); + } + + final progressBar = ProgressBar( + levelBars: [ + LevelBarDetails( + fillColor: const Color.fromARGB(255, 0, 190, 83), + currentPoints: currentXP, + ), + LevelBarDetails( + fillColor: Theme.of(context).colorScheme.primary, + currentPoints: serverXP, + ), + ], + progressBarDetails: ProgressBarDetails( + totalWidth: levelBarWidth, + borderColor: Theme.of(context).colorScheme.primary.withOpacity(0.5), + ), + ); + + final levelBadge = Container( + width: 32, + height: 32, + decoration: BoxDecoration( + color: levelColor(level), + borderRadius: BorderRadius.circular(32), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + blurRadius: 5, + offset: const Offset(5, 0), + ), + ], + ), + child: Center( + child: Text( + "$level", + style: const TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ); + + return Stack( + alignment: Alignment.topCenter, + children: [ + // const Positioned( + // child: PointsGainedAnimation(), + // ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(46, 0, 32, 4), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + FutureBuilder( + future: _pangeaController.matrixState.client + .getProfileFromUserId( + _pangeaController.matrixState.client.userID!, + ), + builder: (context, snapshot) { + final mxid = Matrix.of(context).client.userID ?? + L10n.of(context)!.user; + return Avatar( + name: snapshot.data?.displayName ?? + mxid.localpart ?? + mxid, + mxContent: snapshot.data?.avatarUrl, + size: 40, + ); + }, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: ProgressIndicatorEnum.values + .where( + (indicator) => + indicator != ProgressIndicatorEnum.level, + ) + .map( + (indicator) => ProgressIndicatorBadge( + points: getProgressPoints(indicator), + onTap: () { + final model = getConstructsModel(indicator); + if (model == null) return; + showDialog( + context: context, + builder: (c) => AnalyticsPopup( + indicator: indicator, + constructsModel: model, + ), + ); + }, + progressIndicator: indicator, + loading: loading, + ), + ) + .toList(), + ), + ], + ), + ), + Container( + height: 36, + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Stack( + alignment: Alignment.center, + children: [ + Positioned(left: 16, right: 0, child: progressBar), + Positioned(left: 0, child: levelBadge), + ], + ), + ), + const SizedBox(height: 16), + ], + ), + ], + ); + } +} diff --git a/lib/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart b/lib/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart new file mode 100644 index 000000000..bd24b206f --- /dev/null +++ b/lib/pangea/widgets/chat_list/analytics_summary/progress_indicator.dart @@ -0,0 +1,59 @@ +import 'package:fluffychat/pangea/enum/progress_indicators_enum.dart'; +import 'package:flutter/material.dart'; + +/// A badge that represents one learning progress indicator (i.e., construct uses) +class ProgressIndicatorBadge extends StatelessWidget { + final int? points; + final VoidCallback onTap; + final ProgressIndicatorEnum progressIndicator; + final bool loading; + + const ProgressIndicatorBadge({ + super.key, + required this.points, + required this.onTap, + required this.progressIndicator, + required this.loading, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5), + child: Tooltip( + message: progressIndicator.tooltip(context), + child: InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + progressIndicator.icon, + color: progressIndicator.color(context), + ), + const SizedBox(width: 5), + !loading + ? Text( + points?.toString() ?? '0', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ) + : const SizedBox( + height: 8, + width: 8, + child: CircularProgressIndicator.adaptive( + strokeWidth: 2, + ), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/pangea/widgets/chat_list/chat_list_header_wrapper.dart b/lib/pangea/widgets/chat_list/chat_list_header_wrapper.dart deleted file mode 100644 index 7944f37ab..000000000 --- a/lib/pangea/widgets/chat_list/chat_list_header_wrapper.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'dart:async'; - -import 'package:fluffychat/pages/chat_list/chat_list.dart'; -import 'package:fluffychat/pages/chat_list/chat_list_header.dart'; -import 'package:flutter/material.dart'; - -/// A wrapper around ChatListHeader to allow rebuilding on state changes. -/// Prevents having to rebuild the entire ChatList when a single item changes. -class ChatListHeaderWrapper extends StatefulWidget { - final ChatListController controller; - final bool globalSearch; - - const ChatListHeaderWrapper({ - super.key, - required this.controller, - this.globalSearch = true, - }); - - @override - ChatListHeaderWrapperState createState() => ChatListHeaderWrapperState(); -} - -class ChatListHeaderWrapperState extends State { - StreamSubscription? stateSub; - - @override - void initState() { - super.initState(); - stateSub = widget.controller.selectionsStream.stream.listen((roomID) { - setState(() {}); - }); - } - - @override - void dispose() { - stateSub?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return ChatListHeader( - controller: widget.controller, - globalSearch: widget.globalSearch, - ); - } -} diff --git a/lib/pangea/widgets/chat_list/chat_list_item_wrapper.dart b/lib/pangea/widgets/chat_list/chat_list_item_wrapper.dart deleted file mode 100644 index 2d500bf93..000000000 --- a/lib/pangea/widgets/chat_list/chat_list_item_wrapper.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'dart:async'; - -import 'package:fluffychat/pages/chat_list/chat_list.dart'; -import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; -import 'package:fluffychat/pages/chat_list/utils/on_chat_tap.dart'; -import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; - -/// A wrapper around ChatListItem to allow rebuilding on state changes. -/// Prevents having to rebuild the entire ChatList when a single item changes. -class ChatListItemWrapper extends StatefulWidget { - final Room room; - final bool activeChat; - final void Function()? onForget; - final String? filter; - final ChatListController controller; - - final void Function()? onLongPress; - final void Function()? onTap; - - const ChatListItemWrapper( - this.room, { - this.activeChat = false, - this.onForget, - this.filter, - required this.controller, - this.onLongPress, - this.onTap, - super.key, - }); - - @override - ChatListItemWrapperState createState() => ChatListItemWrapperState(); -} - -class ChatListItemWrapperState extends State { - StreamSubscription? stateSub; - - @override - void initState() { - super.initState(); - stateSub = widget.controller.selectionsStream.stream.listen((roomID) { - if (roomID == widget.room.id) { - setState(() {}); - } - }); - } - - @override - void dispose() { - stateSub?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return ChatListItem( - widget.room, - activeChat: widget.activeChat, - selected: widget.controller.selectedRoomIds.contains(widget.room.id), - onTap: widget.onTap ?? - (widget.controller.selectMode == SelectMode.select - ? () => widget.controller.toggleSelection(widget.room.id) - : () => onChatTap(widget.room, context)), - onLongPress: widget.onLongPress ?? - () => widget.controller.toggleSelection(widget.room.id), - onForget: widget.onForget, - filter: widget.filter, - ); - } -} diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 26046f8d0..5ddf1b0c5 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -1,11 +1,14 @@ import 'dart:developer'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/enum/construct_use_type_enum.dart'; import 'package:fluffychat/pangea/enum/span_data_type.dart'; +import 'package:fluffychat/pangea/models/pangea_token_model.dart'; import 'package:fluffychat/pangea/models/span_data.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/match_copy.dart'; +import 'package:fluffychat/pangea/widgets/animations/gain_points.dart'; import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -20,8 +23,6 @@ import '../common/bot_face_svg.dart'; import 'card_header.dart'; import 'why_button.dart'; -const wordMatchResultsCount = 5; - //switch for definition vs correction vs practice //always show a title @@ -32,12 +33,12 @@ const wordMatchResultsCount = 5; class SpanCard extends StatefulWidget { final PangeaController pangeaController = MatrixState.pangeaController; final SpanCardModel scm; - final String? roomId; + final String roomId; SpanCard({ super.key, required this.scm, - this.roomId, + required this.roomId, }); @override @@ -62,12 +63,16 @@ class SpanCardState extends State { //get selected choice SpanChoice? get selectedChoice { - if (selectedChoiceIndex == null || - widget.scm.pangeaMatch?.match.choices == null || - widget.scm.pangeaMatch!.match.choices!.length <= selectedChoiceIndex!) { + if (selectedChoiceIndex == null) return null; + return choiceByIndex(selectedChoiceIndex!); + } + + SpanChoice? choiceByIndex(int index) { + if (widget.scm.pangeaMatch?.match.choices == null || + widget.scm.pangeaMatch!.match.choices!.length <= index) { return null; } - return widget.scm.pangeaMatch?.match.choices?[selectedChoiceIndex!]; + return widget.scm.pangeaMatch?.match.choices?[index]; } void fetchSelected() { @@ -76,8 +81,9 @@ class SpanCardState extends State { } if (selectedChoiceIndex == null) { DateTime? mostRecent; - for (int i = 0; i < widget.scm.pangeaMatch!.match.choices!.length; i++) { - final choice = widget.scm.pangeaMatch?.match.choices![i]; + final numChoices = widget.scm.pangeaMatch!.match.choices!.length; + for (int i = 0; i < numChoices; i++) { + final choice = choiceByIndex(i); if (choice!.timestamp != null && (mostRecent == null || choice.timestamp!.isAfter(mostRecent))) { mostRecent = choice.timestamp; @@ -114,6 +120,71 @@ class SpanCardState extends State { } } + Future onChoiceSelect(int index) async { + selectedChoiceIndex = index; + if (selectedChoice != null) { + if (!selectedChoice!.selected) { + MatrixState.pangeaController.myAnalytics.addDraftUses( + selectedChoice!.tokens, + widget.roomId, + selectedChoice!.isBestCorrection + ? ConstructUseTypeEnum.corIGC + : ConstructUseTypeEnum.incIGC, + ); + } + + selectedChoice!.timestamp = DateTime.now(); + selectedChoice!.selected = true; + setState( + () => (selectedChoice!.isBestCorrection + ? BotExpression.gold + : BotExpression.surprised), + ); + } + } + + /// Returns the list of choices that are not selected + List? get ignoredMatches => widget.scm.pangeaMatch?.match.choices + ?.where((choice) => !choice.selected) + .toList(); + + /// Returns the list of tokens from choices that are not selected + List? get ignoredTokens => ignoredMatches + ?.expand((choice) => choice.tokens) + .toList() + .cast(); + + /// Adds the ignored tokens to locally cached analytics + void addIgnoredTokenUses() { + MatrixState.pangeaController.myAnalytics.addDraftUses( + ignoredTokens ?? [], + widget.roomId, + ConstructUseTypeEnum.ignIGC, + ); + } + + void onReplaceSelected() { + addIgnoredTokenUses(); + widget.scm + .onReplacementSelect( + matchIndex: widget.scm.matchIndex, + choiceIndex: selectedChoiceIndex!, + ) + .then((value) => setState(() {})); + } + + void onIgnoreMatch() { + MatrixState.pAnyState.closeOverlay(); + addIgnoredTokenUses(); + + Future.delayed( + Duration.zero, + () { + widget.scm.onIgnore(); + }, + ); + } + @override Widget build(BuildContext context) { return WordMatchContent(controller: this); @@ -129,61 +200,6 @@ class WordMatchContent extends StatelessWidget { super.key, }); - Future onChoiceSelect(int index) async { - controller.selectedChoiceIndex = index; - controller - .widget - .scm - .choreographer - .igc - .igcTextData - ?.matches[controller.widget.scm.matchIndex] - .match - .choices?[index] - .timestamp = DateTime.now(); - controller - .widget - .scm - .choreographer - .igc - .igcTextData - ?.matches[controller.widget.scm.matchIndex] - .match - .choices?[index] - .selected = true; - - controller.setState( - () => (controller.currentExpression = controller - .widget - .scm - .choreographer - .igc - .igcTextData! - .matches[controller.widget.scm.matchIndex] - .match - .choices![index] - .isBestCorrection - ? BotExpression.gold - : BotExpression.surprised), - ); - // if (controller.widget.scm.pangeaMatch.match.choices![index].type == - // SpanChoiceType.distractor) { - // await controller.getSpanDetails(); - // } - // controller.setState(() {}); - } - - void onReplaceSelected() { - controller.widget.scm - .onReplacementSelect( - matchIndex: controller.widget.scm.matchIndex, - choiceIndex: controller.selectedChoiceIndex!, - ) - .then((value) { - controller.setState(() {}); - }); - } - @override Widget build(BuildContext context) { if (controller.widget.scm.pangeaMatch == null) { @@ -205,154 +221,158 @@ class WordMatchContent extends StatelessWidget { final ScrollController scrollController = ScrollController(); try { - return Column( + return Stack( + alignment: Alignment.topCenter, children: [ - // if (!controller.widget.scm.pangeaMatch!.isITStart) - CardHeader( - text: controller.error?.toString() ?? matchCopy.title, - botExpression: controller.error == null - ? controller.currentExpression - : BotExpression.addled, + const Positioned( + top: 40, + child: PointsGainedAnimation(), ), - Expanded( - child: Scrollbar( - controller: scrollController, - thumbVisibility: true, - child: SingleChildScrollView( - controller: scrollController, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // const SizedBox(height: 10.0), - // if (matchCopy.description != null) - // Padding( - // padding: const EdgeInsets.only(), - // child: Text( - // matchCopy.description!, - // style: BotStyle.text(context), - // ), - // ), - const SizedBox(height: 8), - if (!controller.widget.scm.pangeaMatch!.isITStart) - ChoicesArray( - originalSpan: - controller.widget.scm.pangeaMatch!.matchContent, - isLoading: controller.fetchingData, - choices: - controller.widget.scm.pangeaMatch!.match.choices - ?.map( - (e) => Choice( - text: e.value, - color: e.selected ? e.type.color : null, - isGold: e.type.name == 'bestCorrection', - ), - ) - .toList(), - onPressed: onChoiceSelect, - uniqueKeyForLayerLink: (int index) => "wordMatch$index", - selectedChoiceIndex: controller.selectedChoiceIndex, - ), - const SizedBox(height: 12), - PromptAndFeedback(controller: controller), - ], - ), - ), - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + Column( children: [ - const SizedBox(width: 10), + // if (!controller.widget.scm.pangeaMatch!.isITStart) + CardHeader( + text: controller.error?.toString() ?? matchCopy.title, + botExpression: controller.error == null + ? controller.currentExpression + : BotExpression.addled, + ), Expanded( - child: Opacity( - opacity: 0.8, - child: TextButton( - style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( - AppConfig.primaryColor.withOpacity(0.1), - ), - ), - onPressed: () { - MatrixState.pAnyState.closeOverlay(); - Future.delayed( - Duration.zero, - () => controller.widget.scm.onIgnore(), - ); - }, - child: Center( - child: Text(L10n.of(context)!.ignoreInThisText), + child: Scrollbar( + controller: scrollController, + thumbVisibility: true, + child: SingleChildScrollView( + controller: scrollController, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // const SizedBox(height: 10.0), + // if (matchCopy.description != null) + // Padding( + // padding: const EdgeInsets.only(), + // child: Text( + // matchCopy.description!, + // style: BotStyle.text(context), + // ), + // ), + const SizedBox(height: 8), + if (!controller.widget.scm.pangeaMatch!.isITStart) + ChoicesArray( + originalSpan: + controller.widget.scm.pangeaMatch!.matchContent, + isLoading: controller.fetchingData, + choices: + controller.widget.scm.pangeaMatch!.match.choices + ?.map( + (e) => Choice( + text: e.value, + color: e.selected ? e.type.color : null, + isGold: e.type.name == 'bestCorrection', + ), + ) + .toList(), + onPressed: controller.onChoiceSelect, + uniqueKeyForLayerLink: (int index) => + "wordMatch$index", + selectedChoiceIndex: controller.selectedChoiceIndex, + ), + const SizedBox(height: 12), + PromptAndFeedback(controller: controller), + ], ), ), ), ), - const SizedBox(width: 10), - if (!controller.widget.scm.pangeaMatch!.isITStart) - Expanded( - child: Opacity( - opacity: controller.selectedChoiceIndex != null ? 1.0 : 0.5, - child: TextButton( - onPressed: controller.selectedChoiceIndex != null - ? onReplaceSelected - : null, - style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( - (controller.selectedChoice != null - ? controller.selectedChoice!.color - : AppConfig.primaryColor) - .withOpacity(0.2), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(width: 10), + Expanded( + child: Opacity( + opacity: 0.8, + child: TextButton( + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all( + AppConfig.primaryColor.withOpacity(0.1), + ), + ), + onPressed: controller.onIgnoreMatch, + child: Center( + child: Text(L10n.of(context)!.ignoreInThisText), ), - // Outline if Replace button enabled - side: controller.selectedChoice != null - ? WidgetStateProperty.all( - BorderSide( - color: controller.selectedChoice!.color, - style: BorderStyle.solid, - width: 2.0, - ), - ) - : null, ), - child: Text(L10n.of(context)!.replace), ), ), - ), - const SizedBox(width: 10), + const SizedBox(width: 10), + if (!controller.widget.scm.pangeaMatch!.isITStart) + Expanded( + child: Opacity( + opacity: + controller.selectedChoiceIndex != null ? 1.0 : 0.5, + child: TextButton( + onPressed: controller.selectedChoiceIndex != null + ? controller.onReplaceSelected + : null, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all( + (controller.selectedChoice != null + ? controller.selectedChoice!.color + : AppConfig.primaryColor) + .withOpacity(0.2), + ), + // Outline if Replace button enabled + side: controller.selectedChoice != null + ? WidgetStateProperty.all( + BorderSide( + color: controller.selectedChoice!.color, + style: BorderStyle.solid, + width: 2.0, + ), + ) + : null, + ), + child: Text(L10n.of(context)!.replace), + ), + ), + ), + const SizedBox(width: 10), + if (controller.widget.scm.pangeaMatch!.isITStart) + Expanded( + child: TextButton( + onPressed: () { + MatrixState.pAnyState.closeOverlay(); + Future.delayed( + Duration.zero, + () => controller.widget.scm.onITStart(), + ); + }, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all( + (AppConfig.primaryColor).withOpacity(0.1), + ), + ), + child: Text(L10n.of(context)!.helpMeTranslate), + ), + ), + ], + ), if (controller.widget.scm.pangeaMatch!.isITStart) - Expanded( - child: TextButton( - onPressed: () { - MatrixState.pAnyState.closeOverlay(); - Future.delayed( - Duration.zero, - () => controller.widget.scm.onITStart(), - ); - }, - style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( - (AppConfig.primaryColor).withOpacity(0.1), - ), - ), - child: Text(L10n.of(context)!.helpMeTranslate), - ), + DontShowSwitchListTile( + controller: pangeaController, + onSwitch: (bool value) { + pangeaController.userController.updateProfile((profile) { + profile.userSettings.itAutoPlay = value; + return profile; + }); + }, ), ], ), - if (controller.widget.scm.pangeaMatch!.isITStart) - DontShowSwitchListTile( - controller: pangeaController, - onSwitch: (bool value) { - pangeaController.userController.updateProfile((profile) { - profile.userSettings.itAutoPlay = value; - return profile; - }); - }, - ), ], ); } on Exception catch (e) { debugger(when: kDebugMode); ErrorHandler.logError(e: e, s: StackTrace.current); - print(e); rethrow; } } diff --git a/lib/pangea/widgets/igc/span_data.dart b/lib/pangea/widgets/igc/span_data.dart deleted file mode 100644 index a92f32f74..000000000 --- a/lib/pangea/widgets/igc/span_data.dart +++ /dev/null @@ -1,184 +0,0 @@ -//Possible actions/effects from cards -// Nothing -// useType of viewed definitions -// SpanChoice of text in message from options -// Call to server for additional/followup info - -import 'package:collection/collection.dart'; - -import '../../enum/span_data_type.dart'; - -class SpanData { - String? message; - String? shortMessage; - List? choices; - List? replacements; - int offset; - int length; - String fullText; - Context? context; - SpanDataTypeEnum type; - Rule? rule; - - SpanData({ - this.message, - this.shortMessage, - this.choices, - this.replacements, - required this.offset, - required this.length, - required this.fullText, - this.context, - required this.type, - this.rule, - }); - - factory SpanData.fromJson(Map json) { - return SpanData( - message: json['message'], - shortMessage: json['shortMessage'], - choices: json['choices'] != null - ? List.from( - json['choices'].map((x) => SpanChoice.fromJson(x)), - ) - : null, - replacements: json['replacements'] != null - ? List.from( - json['replacements'].map((x) => Replacement.fromJson(x)), - ) - : null, - offset: json['offset'], - length: json['length'], - fullText: json['full_text'], - context: - json['context'] != null ? Context.fromJson(json['context']) : null, - type: SpanDataTypeEnum.values.firstWhereOrNull( - (e) => e.toString() == 'SpanDataTypeEnum.${json['type']}', - ) ?? - SpanDataTypeEnum.correction, - rule: json['rule'] != null ? Rule.fromJson(json['rule']) : null, - ); - } - - Map toJson() { - final Map data = {}; - data['message'] = message; - data['shortMessage'] = shortMessage; - if (choices != null) { - data['choices'] = choices!.map((x) => x.toJson()).toList(); - } - if (replacements != null) { - data['replacements'] = replacements!.map((x) => x.toJson()).toList(); - } - data['offset'] = offset; - data['length'] = length; - data['full_text'] = fullText; - if (context != null) { - data['context'] = context!.toJson(); - } - data['type'] = type.toString().split('.').last; - if (rule != null) { - data['rule'] = rule!.toJson(); - } - return data; - } -} - -class Context { - String sentence; - int offset; - int length; - - Context({required this.sentence, required this.offset, required this.length}); - - factory Context.fromJson(Map json) { - return Context( - sentence: json['sentence'], - offset: json['offset'], - length: json['length'], - ); - } - - Map toJson() { - final Map data = {}; - data['sentence'] = sentence; - data['offset'] = offset; - data['length'] = length; - return data; - } -} - -class SpanChoice { - String value; - bool selected; - - SpanChoice({required this.value, required this.selected}); - - factory SpanChoice.fromJson(Map json) { - return SpanChoice( - value: json['value'], - selected: json['selected'], - ); - } - - Map toJson() { - final Map data = {}; - data['value'] = value; - data['selected'] = selected; - return data; - } -} - -class Replacement { - String value; - - Replacement({required this.value}); - - factory Replacement.fromJson(Map json) { - return Replacement( - value: json['value'], - ); - } - - Map toJson() { - final Map data = {}; - data['value'] = value; - return data; - } -} - -class Rule { - String id; - - Rule({required this.id}); - - factory Rule.fromJson(Map json) { - return Rule( - id: json['id'], - ); - } - - Map toJson() { - final Map data = {}; - data['id'] = id; - return data; - } -} - -class SpanDataType { - String type; - - SpanDataType({required this.type}); - - factory SpanDataType.fromJson(Map json) { - return SpanDataType( - type: json['type'], - ); - } - - Map toJson() { - final Map data = {}; - data['type'] = type; - return data; - } -} diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index 5d0b81662..6e24c9e8b 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -1,4 +1,5 @@ import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pangea/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart'; import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart'; import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart'; @@ -102,6 +103,20 @@ class MessagePracticeActivityCardState extends State { }, ); return null; + }).then((event) { + // The record event is processed into construct uses for learning analytics, so if the + // event went through without error, send it to analytics to be processed + if (event != null && currentActivity != null) { + MatrixState.pangeaController.myAnalytics.setState( + data: { + 'eventID': widget.pangeaMessageEvent.eventId, + 'eventType': PangeaEventTypes.activityRecord, + 'roomID': event.room.id, + 'practiceActivity': currentActivity!, + 'recordModel': currentRecordModel!, + }, + ); + } }).whenComplete(() => setState(() => sending = false)); } diff --git a/lib/pangea/widgets/user_settings/p_language_dialog.dart b/lib/pangea/widgets/user_settings/p_language_dialog.dart index bfc85528b..43096ea54 100644 --- a/lib/pangea/widgets/user_settings/p_language_dialog.dart +++ b/lib/pangea/widgets/user_settings/p_language_dialog.dart @@ -91,15 +91,30 @@ Future pLanguageDialog( context: context, future: () async { try { - pangeaController.userController - .updateProfile((profile) { - profile.userSettings.sourceLanguage = - selectedSourceLanguage.langCode; - profile.userSettings.targetLanguage = - selectedTargetLanguage.langCode; - return profile; + pangeaController.myAnalytics + .updateAnalytics() + .then((_) { + pangeaController.userController.updateProfile( + (profile) { + profile.userSettings.sourceLanguage = + selectedSourceLanguage.langCode; + profile.userSettings.targetLanguage = + selectedTargetLanguage.langCode; + return profile; + }, + waitForDataInSync: true, + ); + }).then((_) { + // if the profile update is successful, reset cached analytics + // data, since analytics data corresponds to the user's L2 + pangeaController.myAnalytics.dispose(); + pangeaController.analytics.dispose(); + + pangeaController.myAnalytics.initialize(); + pangeaController.analytics.initialize(); + + Navigator.pop(context); }); - Navigator.pop(context); } catch (err, s) { debugger(when: kDebugMode); ErrorHandler.logError(e: err, s: s); diff --git a/lib/utils/adaptive_bottom_sheet.dart b/lib/utils/adaptive_bottom_sheet.dart index cfe487ffd..d21ca6c44 100644 --- a/lib/utils/adaptive_bottom_sheet.dart +++ b/lib/utils/adaptive_bottom_sheet.dart @@ -8,18 +8,19 @@ Future showAdaptiveBottomSheet({ required Widget Function(BuildContext) builder, bool isDismissible = true, bool isScrollControlled = true, - double maxHeight = 480.0, + double maxHeight = 512, + bool useRootNavigator = true, }) => showModalBottomSheet( context: context, builder: builder, // this sadly is ugly on desktops but otherwise breaks `.of(context)` calls - useRootNavigator: false, + useRootNavigator: useRootNavigator, isDismissible: isDismissible, isScrollControlled: isScrollControlled, constraints: BoxConstraints( maxHeight: maxHeight, - maxWidth: FluffyThemes.columnWidth * 1.5, + maxWidth: FluffyThemes.columnWidth * 1.25, ), clipBehavior: Clip.hardEdge, shape: const RoundedRectangleBorder( diff --git a/lib/utils/client_download_content_extension.dart b/lib/utils/client_download_content_extension.dart new file mode 100644 index 000000000..9fff1eccd --- /dev/null +++ b/lib/utils/client_download_content_extension.dart @@ -0,0 +1,53 @@ +import 'dart:typed_data'; + +import 'package:matrix/matrix.dart'; + +extension ClientDownloadContentExtension on Client { + Future downloadMxcCached( + Uri mxc, { + num? width, + num? height, + bool isThumbnail = false, + bool? animated, + ThumbnailMethod? thumbnailMethod, + }) async { + // To stay compatible with previous storeKeys: + final cacheKey = isThumbnail + // ignore: deprecated_member_use + ? mxc.getThumbnail( + this, + width: width, + height: height, + animated: animated, + method: thumbnailMethod!, + ) + : mxc; + + final cachedData = await database?.getFile(cacheKey); + if (cachedData != null) return cachedData; + + final httpUri = isThumbnail + ? await mxc.getThumbnailUri( + this, + width: width, + height: height, + animated: animated, + method: thumbnailMethod, + ) + : await mxc.getDownloadUri(this); + + final response = await httpClient.get( + httpUri, + headers: + accessToken == null ? null : {'authorization': 'Bearer $accessToken'}, + ); + if (response.statusCode != 200) { + throw Exception(); + } + final remoteData = response.bodyBytes; + + await database?.storeFile(cacheKey, remoteData, 0); + + return remoteData; + } +} diff --git a/lib/utils/client_manager.dart b/lib/utils/client_manager.dart index 808dfd9fc..5ea52f5e5 100644 --- a/lib/utils/client_manager.dart +++ b/lib/utils/client_manager.dart @@ -139,7 +139,6 @@ abstract class ClientManager { timeline: StateFilter( notTypes: [ PangeaEventTypes.construct, - PangeaEventTypes.summaryAnalytics, ], ), ), diff --git a/lib/utils/date_time_extension.dart b/lib/utils/date_time_extension.dart index 121eaf72e..0346dd289 100644 --- a/lib/utils/date_time_extension.dart +++ b/lib/utils/date_time_extension.dart @@ -34,14 +34,10 @@ extension DateTimeExtension on DateTime { } /// Returns a simple time String. - /// TODO: Add localization - String localizedTimeOfDay(BuildContext context) { - if (MediaQuery.of(context).alwaysUse24HourFormat) { - return '${_z(hour)}:${_z(minute)}'; - } else { - return '${_z(hour % 12 == 0 ? 12 : hour % 12)}:${_z(minute)} ${hour > 11 ? "pm" : "am"}'; - } - } + String localizedTimeOfDay(BuildContext context) => + L10n.of(context)!.alwaysUse24HourFormat == 'true' + ? DateFormat('HH:mm', L10n.of(context)!.localeName).format(this) + : DateFormat('h:mm a', L10n.of(context)!.localeName).format(this); /// Returns [localizedTimeOfDay()] if the ChatTime is today, the name of the week /// day if the ChatTime is this week and a date string else. @@ -60,19 +56,14 @@ extension DateTimeExtension on DateTime { if (sameDay) { return localizedTimeOfDay(context); } else if (sameWeek) { - return DateFormat.EEEE(Localizations.localeOf(context).languageCode) + return DateFormat.E(Localizations.localeOf(context).languageCode) .format(this); } else if (sameYear) { - return L10n.of(context)!.dateWithoutYear( - month.toString().padLeft(2, '0'), - day.toString().padLeft(2, '0'), - ); + return DateFormat.MMMd(Localizations.localeOf(context).languageCode) + .format(this); } - return L10n.of(context)!.dateWithYear( - year.toString(), - month.toString().padLeft(2, '0'), - day.toString().padLeft(2, '0'), - ); + return DateFormat.yMMMd(Localizations.localeOf(context).languageCode) + .format(this); } /// If the DateTime is today, this returns [localizedTimeOfDay()], if not it also @@ -91,6 +82,4 @@ extension DateTimeExtension on DateTime { localizedTimeOfDay(context), ); } - - static String _z(int i) => i < 10 ? '0${i.toString()}' : i.toString(); } diff --git a/lib/utils/localized_exception_extension.dart b/lib/utils/localized_exception_extension.dart index 5b2df02fd..fe585a7d1 100644 --- a/lib/utils/localized_exception_extension.dart +++ b/lib/utils/localized_exception_extension.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:http/http.dart'; import 'package:matrix/encryption.dart'; import 'package:matrix/matrix.dart'; @@ -66,9 +67,16 @@ extension LocalizedExceptionExtension on Object { supportedVersions, ); } - if (this is SocketException || this is SyncConnectionException) { + if (this is IOException || + this is SocketException || + this is SyncConnectionException || + this is ClientException) { return L10n.of(context)!.noConnectionToTheServer; } + if (this is FormatException && + exceptionContext == ExceptionContext.checkHomeserver) { + return L10n.of(context)!.doesNotSeemToBeAValidHomeserver; + } if (this is String) return toString(); if (this is UiaException) return toString(); Logs().w('Something went wrong: ', this); @@ -78,4 +86,5 @@ extension LocalizedExceptionExtension on Object { enum ExceptionContext { changePassword, + checkHomeserver, } diff --git a/lib/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart b/lib/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart index 1fb9a4e4c..d10a09bd3 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart @@ -82,7 +82,7 @@ class FlutterHiveCollectionsDatabase extends HiveCollectionsDatabase { } static Future findDatabasePath(Client client) async { - String path = client.clientName; + var path = client.clientName; if (!kIsWeb) { Directory directory; try { diff --git a/lib/utils/platform_infos.dart b/lib/utils/platform_infos.dart index 350fc914f..83d4c9e74 100644 --- a/lib/utils/platform_infos.dart +++ b/lib/utils/platform_infos.dart @@ -28,9 +28,10 @@ abstract class PlatformInfos { static bool get usesTouchscreen => !isMobile; - // #Pangea + /// Web could also record in theory but currently only wav which is too large + /// #Pangea // static bool get platformCanRecord => (isMobile || isMacOS); - static bool get platformCanRecord => (isMobile || isMacOS || kIsWeb); + static bool get platformCanRecord => (isMobile || isMacOS || isWeb); // Pangea# static String get clientName => diff --git a/lib/utils/push_helper.dart b/lib/utils/push_helper.dart index 3290ae086..eae5eaf43 100644 --- a/lib/utils/push_helper.dart +++ b/lib/utils/push_helper.dart @@ -1,16 +1,15 @@ -import 'dart:io'; import 'dart:ui'; import 'package:collection/collection.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:fluffychat/utils/client_download_content_extension.dart'; import 'package:fluffychat/utils/client_manager.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/voip/callkeep_manager.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_shortcuts/flutter_shortcuts.dart'; @@ -179,28 +178,25 @@ Future _tryPushHelper( ); // The person object for the android message style notification - final avatar = event.room.avatar - ?.getThumbnail( - client, - width: 256, - height: 256, - ) - .toString(); + final avatar = event.room.avatar; final senderAvatar = event.room.isDirectChat ? avatar - : event.senderFromMemoryOrFallback.avatarUrl - ?.getThumbnail( - client, - width: 256, - height: 256, - ) - .toString(); + : event.senderFromMemoryOrFallback.avatarUrl; - File? roomAvatarFile, senderAvatarFile; + Uint8List? roomAvatarFile, senderAvatarFile; try { roomAvatarFile = avatar == null ? null - : await DefaultCacheManager().getSingleFile(avatar); + : await client + .downloadMxcCached( + avatar, + thumbnailMethod: ThumbnailMethod.scale, + width: 256, + height: 256, + animated: false, + isThumbnail: true, + ) + .timeout(const Duration(seconds: 3)); } catch (e, s) { Logs().e('Unable to get avatar picture', e, s); // #Pangea @@ -212,7 +208,16 @@ Future _tryPushHelper( ? roomAvatarFile : senderAvatar == null ? null - : await DefaultCacheManager().getSingleFile(senderAvatar); + : await client + .downloadMxcCached( + senderAvatar, + thumbnailMethod: ThumbnailMethod.scale, + width: 256, + height: 256, + animated: false, + isThumbnail: true, + ) + .timeout(const Duration(seconds: 3)); } catch (e, s) { Logs().e('Unable to get avatar picture', e, s); } @@ -230,7 +235,7 @@ Future _tryPushHelper( name: event.senderFromMemoryOrFallback.calcDisplayname(), icon: senderAvatarFile == null ? null - : BitmapFilePathAndroidIcon(senderAvatarFile.path), + : ByteArrayAndroidIcon(senderAvatarFile), ), ); @@ -277,7 +282,7 @@ Future _tryPushHelper( name: event.senderFromMemoryOrFallback.calcDisplayname(), icon: roomAvatarFile == null ? null - : BitmapFilePathAndroidIcon(roomAvatarFile.path), + : ByteArrayAndroidIcon(roomAvatarFile), key: event.roomId, important: event.room.isFavourite, ), @@ -326,7 +331,7 @@ Future _setShortcut( Event event, L10n l10n, String title, - File? avatarFile, + Uint8List? avatarFile, ) async { final flutterShortcuts = FlutterShortcuts(); await flutterShortcuts.initialize(debug: !kReleaseMode); @@ -338,8 +343,7 @@ Future _setShortcut( conversationShortcut: true, icon: avatarFile == null ? null - : ShortcutMemoryIcon(jpegImage: await avatarFile.readAsBytes()) - .toString(), + : ShortcutMemoryIcon(jpegImage: avatarFile).toString(), shortcutIconAsset: avatarFile == null ? ShortcutIconAsset.androidAsset : ShortcutIconAsset.memoryAsset, diff --git a/lib/utils/show_update_snackbar.dart b/lib/utils/show_update_snackbar.dart new file mode 100644 index 000000000..eece3b4fb --- /dev/null +++ b/lib/utils/show_update_snackbar.dart @@ -0,0 +1,51 @@ +import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +abstract class UpdateNotifier { + static const String versionStoreKey = 'last_known_version'; + + static void showUpdateSnackBar(BuildContext context) async { + final theme = Theme.of(context); + final scaffoldMessenger = ScaffoldMessenger.of(context); + final currentVersion = await PlatformInfos.getVersion(); + final store = await SharedPreferences.getInstance(); + final storedVersion = store.getString(versionStoreKey); + + if (currentVersion != storedVersion) { + if (storedVersion != null) { + ScaffoldFeatureController? controller; + controller = scaffoldMessenger.showSnackBar( + SnackBar( + duration: const Duration(seconds: 30), + content: Row( + children: [ + IconButton( + icon: Icon( + Icons.close_outlined, + size: 20, + color: theme.colorScheme.onPrimary, + ), + onPressed: () => controller?.close(), + ), + Expanded( + child: Text( + L10n.of(context)!.updateInstalled(currentVersion), + ), + ), + ], + ), + // #Pangea + // action: SnackBarAction( + // label: L10n.of(context)!.changelog, + // onPressed: () => launchUrlString(AppConfig.changelogUrl), + // ), + // Pangea# + ), + ); + } + await store.setString(versionStoreKey, currentVersion); + } + } +} diff --git a/lib/utils/voip_plugin.dart b/lib/utils/voip_plugin.dart index 8a71390ef..d2ca1f999 100644 --- a/lib/utils/voip_plugin.dart +++ b/lib/utils/voip_plugin.dart @@ -36,7 +36,6 @@ class VoipPlugin with WidgetsBindingObserver implements WebRTCDelegate { void didChangeAppLifecycleState(AppLifecycleState? state) { background = (state == AppLifecycleState.detached || state == AppLifecycleState.paused); - Logs().w('Set background mode in VOIP plugin', background); } void addCallingOverlay(String callId, CallSession call) { diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index 2a80451ca..560fb5e9c 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -1,5 +1,6 @@ import 'package:fluffychat/utils/string_color.dart'; import 'package:fluffychat/widgets/mxc_image.dart'; +import 'package:fluffychat/widgets/presence_builder.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; @@ -12,9 +13,9 @@ class Avatar extends StatelessWidget { final Client? client; final String? presenceUserId; final Color? presenceBackgroundColor; - //#Pangea - final IconData? littleIcon; - // Pangea# + final BorderRadius? borderRadius; + final IconData? icon; + final BorderSide? border; const Avatar({ this.mxContent, @@ -24,14 +25,16 @@ class Avatar extends StatelessWidget { this.client, this.presenceUserId, this.presenceBackgroundColor, - //#Pangea - this.littleIcon, - // Pangea# + this.borderRadius, + this.border, + this.icon, super.key, }); @override Widget build(BuildContext context) { + final theme = Theme.of(context); + var fallbackLetters = '@'; final name = this.name; if (name != null) { @@ -44,105 +47,97 @@ class Avatar extends StatelessWidget { final noPic = mxContent == null || mxContent.toString().isEmpty || mxContent.toString() == 'null'; - final textWidget = Center( + final textColor = name?.lightColorAvatar; + final textWidget = Container( + color: textColor, + alignment: Alignment.center, child: Text( fallbackLetters, style: TextStyle( - color: noPic ? Colors.white : null, - fontSize: (size / 2.5).roundToDouble(), + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: (size / 3).roundToDouble(), ), ), ); - final borderRadius = BorderRadius.circular(size / 2); + final borderRadius = this.borderRadius ?? BorderRadius.circular(size / 2); final presenceUserId = this.presenceUserId; - final color = - noPic ? name?.lightColorAvatar : Theme.of(context).secondaryHeaderColor; final container = Stack( children: [ - ClipRRect( - borderRadius: borderRadius, - child: Container( - width: size, - height: size, - color: color, + SizedBox( + width: size, + height: size, + child: Material( + color: theme.brightness == Brightness.light + ? Colors.white + : Colors.black, + shape: RoundedRectangleBorder( + borderRadius: borderRadius, + side: border ?? BorderSide.none, + ), + clipBehavior: Clip.hardEdge, child: noPic ? textWidget : MxcImage( - key: Key(mxContent.toString()), + client: client, + key: ValueKey(mxContent.toString()), + cacheKey: '${mxContent}_$size', uri: mxContent, fit: BoxFit.cover, width: size, height: size, - placeholder: (_) => textWidget, - cacheKey: mxContent.toString(), + placeholder: (_) => Center( + child: Icon( + Icons.person_2, + color: theme.colorScheme.tertiary, + size: size / 1.5, + ), + ), ), ), ), - // #Pangea - if (littleIcon != null) - Positioned( - bottom: 0, - right: 0, - child: ClipRRect( - borderRadius: borderRadius, - child: Container( - height: 16, - width: 16, - color: Colors.white, - child: Icon( - littleIcon, - color: noPic - ? name?.lightColorAvatar - : Theme.of(context).secondaryHeaderColor, - size: 14, + if (presenceUserId != null) + PresenceBuilder( + client: client, + userId: presenceUserId, + builder: (context, presence) { + if (presence == null || + (presence.presence == PresenceType.offline && + presence.lastActiveTimestamp == null)) { + return const SizedBox.shrink(); + } + final dotColor = presence.presence.isOnline + ? Colors.green + : presence.presence.isUnavailable + ? Colors.orange + : Colors.grey; + return Positioned( + bottom: -3, + right: -3, + child: Container( + width: 16, + height: 16, + decoration: BoxDecoration( + color: presenceBackgroundColor ?? theme.colorScheme.surface, + borderRadius: BorderRadius.circular(32), + ), + alignment: Alignment.center, + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: dotColor, + borderRadius: BorderRadius.circular(16), + border: Border.all( + width: 1, + color: theme.colorScheme.surface, + ), + ), + ), ), - ), - ), + ); + }, ), - // #Pangea - // PresenceBuilder( - // client: client, - // userId: presenceUserId, - // builder: (context, presence) { - // if (presence == null || - // (presence.presence == PresenceType.offline && - // presence.lastActiveTimestamp == null)) { - // return const SizedBox.shrink(); - // } - // final dotColor = presence.presence.isOnline - // ? Colors.green - // : presence.presence.isUnavailable - // ? Colors.orange - // : Colors.grey; - // return Positioned( - // bottom: -3, - // right: -3, - // child: Container( - // width: 16, - // height: 16, - // decoration: BoxDecoration( - // color: presenceBackgroundColor ?? - // Theme.of(context).colorScheme.surface, - // borderRadius: BorderRadius.circular(32), - // ), - // alignment: Alignment.center, - // child: Container( - // width: 10, - // height: 10, - // decoration: BoxDecoration( - // color: dotColor, - // borderRadius: BorderRadius.circular(16), - // border: Border.all( - // width: 1, - // color: Theme.of(context).colorScheme.surface, - // ), - // ), - // ), - // ), - // ); - // }, - // ), - // Pangea# ], ); if (onTap == null) return container; diff --git a/lib/widgets/connection_status_header.dart b/lib/widgets/connection_status_header.dart index 285ebb8bf..eef2b795d 100644 --- a/lib/widgets/connection_status_header.dart +++ b/lib/widgets/connection_status_header.dart @@ -35,6 +35,8 @@ class ConnectionStatusHeaderState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final client = Matrix.of(context).client; final status = client.onSyncStatus.value ?? const SyncStatusUpdate(SyncStatus.waitingForResponse); @@ -65,7 +67,7 @@ class ConnectionStatusHeaderState extends State { status.toLocalizedString(context), maxLines: 1, overflow: TextOverflow.ellipsis, - style: TextStyle(color: Theme.of(context).colorScheme.onSurface), + style: TextStyle(color: theme.colorScheme.onSurface), ), ], ), diff --git a/lib/widgets/layouts/login_scaffold.dart b/lib/widgets/layouts/login_scaffold.dart index e5662417c..c5c6b8c60 100644 --- a/lib/widgets/layouts/login_scaffold.dart +++ b/lib/widgets/layouts/login_scaffold.dart @@ -19,6 +19,8 @@ class LoginScaffold extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final isMobileMode = enforceMobileMode || !FluffyThemes.isColumnMode(context); final scaffold = Scaffold( @@ -56,13 +58,12 @@ class LoginScaffold extends StatelessWidget { child: body, ), ), - // backgroundColor: isMobileMode - // ? null - // : Theme.of(context).colorScheme.surface.withOpacity(0.8), + // backgroundColor: + // isMobileMode ? null : theme.colorScheme.surface.withOpacity(0.8), // bottomNavigationBar: isMobileMode // ? Material( // elevation: 4, - // shadowColor: Theme.of(context).colorScheme.onSurface, + // shadowColor: theme.colorScheme.onSurface, // child: const _PrivacyButtons( // mainAxisAlignment: MainAxisAlignment.center, // ), @@ -91,13 +92,12 @@ class LoginScaffold extends StatelessWidget { // color: Colors.transparent, // borderRadius: BorderRadius.circular(AppConfig.borderRadius), // clipBehavior: Clip.hardEdge, - // elevation: - // Theme.of(context).appBarTheme.scrolledUnderElevation ?? 4, - // shadowColor: Theme.of(context).appBarTheme.shadowColor, + // elevation: theme.appBarTheme.scrolledUnderElevation ?? 4, + // shadowColor: theme.appBarTheme.shadowColor, // child: ConstrainedBox( // constraints: isMobileMode // ? const BoxConstraints() - // : const BoxConstraints(maxWidth: 480, maxHeight: 720), + // : const BoxConstraints(maxWidth: 480, maxHeight: 640), // child: BackdropFilter( // filter: ImageFilter.blur( // sigmaX: 10.0, diff --git a/lib/widgets/layouts/max_width_body.dart b/lib/widgets/layouts/max_width_body.dart index e9499d31e..4e44cc796 100644 --- a/lib/widgets/layouts/max_width_body.dart +++ b/lib/widgets/layouts/max_width_body.dart @@ -1,20 +1,17 @@ -import 'dart:math'; - import 'package:flutter/material.dart'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/themes.dart'; class MaxWidthBody extends StatelessWidget { - final Widget? child; + final Widget child; final double maxWidth; - final bool withFrame; final bool withScrolling; final EdgeInsets? innerPadding; const MaxWidthBody({ - this.child, + required this.child, this.maxWidth = 600, - this.withFrame = true, this.withScrolling = true, this.innerPadding, super.key, @@ -24,36 +21,34 @@ class MaxWidthBody extends StatelessWidget { return SafeArea( child: LayoutBuilder( builder: (context, constraints) { - final paddingVal = max(0, (constraints.maxWidth - maxWidth) / 2); - final hasPadding = paddingVal > 0; - final padding = EdgeInsets.symmetric( - vertical: hasPadding ? 32 : 0, - horizontal: max(0, (constraints.maxWidth - maxWidth) / 2), - ); - final childWithPadding = Padding( - padding: padding, - child: withFrame && hasPadding - ? Material( - elevation: - Theme.of(context).appBarTheme.scrolledUnderElevation ?? - 4, - clipBehavior: Clip.hardEdge, - borderRadius: BorderRadius.circular(AppConfig.borderRadius), - shadowColor: Theme.of(context).appBarTheme.shadowColor, - child: child, - ) - : child, - ); - if (!withScrolling) { - return Padding( - padding: innerPadding ?? EdgeInsets.zero, - child: childWithPadding, - ); - } + final theme = Theme.of(context); + + const desiredWidth = FluffyThemes.columnWidth * 1.5; + final body = constraints.maxWidth <= desiredWidth + ? child + : Container( + alignment: Alignment.topCenter, + padding: const EdgeInsets.all(32), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: FluffyThemes.columnWidth * 1.5, + ), + child: Material( + elevation: theme.appBarTheme.scrolledUnderElevation ?? 4, + clipBehavior: Clip.hardEdge, + borderRadius: + BorderRadius.circular(AppConfig.borderRadius), + shadowColor: theme.appBarTheme.shadowColor, + child: child, + ), + ), + ); + if (!withScrolling) return body; + return SingleChildScrollView( padding: innerPadding, physics: const ScrollPhysics(), - child: childWithPadding, + child: body, ); }, ), diff --git a/lib/widgets/layouts/two_column_layout.dart b/lib/widgets/layouts/two_column_layout.dart index a6f4c8bdf..36e815ebb 100644 --- a/lib/widgets/layouts/two_column_layout.dart +++ b/lib/widgets/layouts/two_column_layout.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:fluffychat/config/themes.dart'; + class TwoColumnLayout extends StatelessWidget { final Widget mainView; final Widget sideView; @@ -13,6 +15,8 @@ class TwoColumnLayout extends StatelessWidget { }); @override Widget build(BuildContext context) { + final theme = Theme.of(context); + return ScaffoldMessenger( child: Scaffold( body: Row( @@ -20,12 +24,13 @@ class TwoColumnLayout extends StatelessWidget { Container( clipBehavior: Clip.antiAlias, decoration: const BoxDecoration(), - width: 360.0 + (displayNavigationRail ? 64 : 0), + width: FluffyThemes.columnWidth + + (displayNavigationRail ? FluffyThemes.navRailWidth : 0), child: mainView, ), Container( width: 1.0, - color: Theme.of(context).dividerColor, + color: theme.dividerColor, ), Expanded( child: ClipRRect( diff --git a/lib/widgets/local_notifications_extension.dart b/lib/widgets/local_notifications_extension.dart index e3d9ff3c4..0953c1deb 100644 --- a/lib/widgets/local_notifications_extension.dart +++ b/lib/widgets/local_notifications_extension.dart @@ -1,20 +1,17 @@ import 'dart:io'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - import 'package:desktop_notifications/desktop_notifications.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; -import 'package:http/http.dart' as http; -import 'package:matrix/matrix.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:universal_html/html.dart' as html; - import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/utils/client_download_content_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart'; +import 'package:universal_html/html.dart' as html; extension LocalNotificationsExtension on MatrixState { static final html.AudioElement _audioPlayer = html.AudioElement() @@ -48,50 +45,47 @@ extension LocalNotificationsExtension on MatrixState { hideEdit: true, removeMarkdown: true, ); - final icon = event.senderFromMemoryOrFallback.avatarUrl?.getThumbnail( - client, - width: 64, - height: 64, - method: ThumbnailMethod.crop, - ) ?? - room.avatar?.getThumbnail( - client, - width: 64, - height: 64, - method: ThumbnailMethod.crop, - ); + if (kIsWeb) { + final avatarUrl = event.senderFromMemoryOrFallback.avatarUrl; + Uri? thumbnailUri; + + if (avatarUrl != null) { + const size = 64; + const thumbnailMethod = ThumbnailMethod.crop; + // Pre-cache so that we can later just set the thumbnail uri as icon: + await client.downloadMxcCached( + avatarUrl, + width: size, + height: size, + thumbnailMethod: thumbnailMethod, + isThumbnail: true, + ); + + thumbnailUri = + await event.senderFromMemoryOrFallback.avatarUrl?.getThumbnailUri( + client, + width: size, + height: size, + method: thumbnailMethod, + ); + } + _audioPlayer.play(); + html.Notification( title, body: body, - icon: icon.toString(), + icon: thumbnailUri?.toString(), + tag: event.room.id, ); } else if (Platform.isLinux) { - final appIconUrl = room.avatar?.getThumbnail( - room.client, - width: 56, - height: 56, - ); - File? appIconFile; - if (appIconUrl != null) { - final tempDirectory = await getApplicationSupportDirectory(); - final avatarDirectory = - await Directory('${tempDirectory.path}/notiavatars/').create(); - appIconFile = File( - '${avatarDirectory.path}/${Uri.encodeComponent(appIconUrl.toString())}', - ); - if (await appIconFile.exists() == false) { - final response = await http.get(appIconUrl); - await appIconFile.writeAsBytes(response.bodyBytes); - } - } final notification = await linuxNotifications!.notify( title, body: body, replacesId: linuxNotificationIds[roomId] ?? 0, appName: AppConfig.applicationName, - appIcon: appIconFile?.path ?? '', + appIcon: 'fluffychat', actions: [ NotificationAction( DesktopNotificationActions.openChat.name, diff --git a/lib/widgets/mxc_image.dart b/lib/widgets/mxc_image.dart index 9290156bf..d776cfc82 100644 --- a/lib/widgets/mxc_image.dart +++ b/lib/widgets/mxc_image.dart @@ -2,10 +2,10 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/themes.dart'; +import 'package:fluffychat/utils/client_download_content_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -23,6 +23,7 @@ class MxcImage extends StatefulWidget { final ThumbnailMethod thumbnailMethod; final Widget Function(BuildContext context)? placeholder; final String? cacheKey; + final Client? client; const MxcImage({ this.uri, @@ -38,6 +39,7 @@ class MxcImage extends StatefulWidget { this.animationCurve = FluffyThemes.animationCurve, this.thumbnailMethod = ThumbnailMethod.scale, this.cacheKey, + this.client, super.key, }); @@ -48,10 +50,10 @@ class MxcImage extends StatefulWidget { class _MxcImageState extends State { static final Map _imageDataCache = {}; Uint8List? _imageDataNoCache; - Uint8List? get _imageData { - final cacheKey = widget.cacheKey; - return cacheKey == null ? _imageDataNoCache : _imageDataCache[cacheKey]; - } + + Uint8List? get _imageData => widget.cacheKey == null + ? _imageDataNoCache + : _imageDataCache[widget.cacheKey]; set _imageData(Uint8List? data) { if (data == null) return; @@ -61,10 +63,8 @@ class _MxcImageState extends State { : _imageDataCache[cacheKey] = data; } - bool? _isCached; - Future _load() async { - final client = Matrix.of(context).client; + final client = widget.client ?? Matrix.of(context).client; final uri = widget.uri; final event = widget.event; @@ -75,45 +75,18 @@ class _MxcImageState extends State { final height = widget.height; final realHeight = height == null ? null : height * devicePixelRatio; - final httpUri = widget.isThumbnail - ? uri.getThumbnail( - client, - width: realWidth, - height: realHeight, - animated: widget.animated, - method: widget.thumbnailMethod, - ) - : uri.getDownloadLink(client); - - final storeKey = widget.isThumbnail ? httpUri : uri; - - if (_isCached == null) { - final cachedData = await client.database?.getFile(storeKey); - if (cachedData != null) { - if (!mounted) return; - setState(() { - _imageData = cachedData; - _isCached = true; - }); - return; - } - _isCached = false; - } - - final response = await http.get(httpUri); - if (response.statusCode != 200) { - if (response.statusCode == 404) { - return; - } - throw Exception(); - } - final remoteData = response.bodyBytes; - + final remoteData = await client.downloadMxcCached( + uri, + width: realWidth, + height: realHeight, + thumbnailMethod: widget.thumbnailMethod, + isThumbnail: widget.isThumbnail, + animated: widget.animated, + ); if (!mounted) return; setState(() { _imageData = remoteData; }); - await client.database?.storeFile(storeKey, remoteData, 0); } if (event != null) { @@ -177,7 +150,6 @@ class _MxcImageState extends State { filterQuality: widget.isThumbnail ? FilterQuality.low : FilterQuality.medium, errorBuilder: (context, __, ___) { - _isCached = false; _imageData = null; WidgetsBinding.instance.addPostFrameCallback(_tryLoad); return placeholder(context); diff --git a/lib/widgets/public_room_bottom_sheet.dart b/lib/widgets/public_room_bottom_sheet.dart index b60b5a1ee..c8e84d53e 100644 --- a/lib/widgets/public_room_bottom_sheet.dart +++ b/lib/widgets/public_room_bottom_sheet.dart @@ -10,19 +10,17 @@ import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; -import '../utils/localized_exception_extension.dart'; - class PublicRoomBottomSheet extends StatelessWidget { final String? roomAlias; final BuildContext outerContext; final PublicRoomsChunk? chunk; - final VoidCallback? onRoomJoined; + final List? via; PublicRoomBottomSheet({ this.roomAlias, required this.outerContext, this.chunk, - this.onRoomJoined, + this.via, super.key, }) { assert(roomAlias != null || chunk != null); @@ -39,8 +37,11 @@ class PublicRoomBottomSheet extends StatelessWidget { return chunk.roomId; } final roomId = chunk != null && knock - ? await client.knockRoom(chunk.roomId) - : await client.joinRoom(roomAlias ?? chunk!.roomId); + ? await client.knockRoom(chunk.roomId, serverName: via) + : await client.joinRoom( + roomAlias ?? chunk!.roomId, + serverName: via, + ); if (!knock && client.getRoomById(roomId) == null) { await client.waitForRoomInSync(roomId); @@ -58,7 +59,7 @@ class PublicRoomBottomSheet extends StatelessWidget { return; } if (result.error == null) { - Navigator.of(context).pop(); + Navigator.of(context).pop(true); // don't open the room if the joined room is a space if (chunk?.roomType != 'm.space' && !client.getRoomById(result.result!)!.isSpace) { @@ -70,17 +71,17 @@ class PublicRoomBottomSheet extends StatelessWidget { bool _testRoom(PublicRoomsChunk r) => r.canonicalAlias == roomAlias; - Future _search(BuildContext context) async { + Future _search() async { final chunk = this.chunk; if (chunk != null) return chunk; - final query = await Matrix.of(context).client.queryPublicRooms( + final query = await Matrix.of(outerContext).client.queryPublicRooms( server: roomAlias!.domain, filter: PublicRoomQueryFilter( genericSearchTerm: roomAlias, ), ); if (!query.chunk.any(_testRoom)) { - throw (L10n.of(context)!.noRoomsFound); + throw (L10n.of(outerContext)!.noRoomsFound); } return query.chunk.firstWhere(_testRoom); } @@ -88,6 +89,7 @@ class PublicRoomBottomSheet extends StatelessWidget { @override Widget build(BuildContext context) { final roomAlias = this.roomAlias ?? chunk?.canonicalAlias; + final roomLink = roomAlias ?? chunk?.roomId; return SafeArea( child: Scaffold( appBar: AppBar( @@ -114,41 +116,84 @@ class PublicRoomBottomSheet extends StatelessWidget { ], ), body: FutureBuilder( - future: _search(context), + future: _search(), builder: (context, snapshot) { + final theme = Theme.of(context); + final profile = snapshot.data; return ListView( padding: EdgeInsets.zero, children: [ - if (profile == null) - Container( - height: 156, - alignment: Alignment.center, - color: Theme.of(context).secondaryHeaderColor, - child: snapshot.hasError - ? Text(snapshot.error!.toLocalizedString(context)) - : const CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), - ) - else - Center( - child: Padding( + Row( + children: [ + Padding( padding: const EdgeInsets.all(16.0), - child: Avatar( - mxContent: profile.avatarUrl, - name: profile.name ?? roomAlias, - size: Avatar.defaultSize * 3, + child: profile == null + ? const Center( + child: CircularProgressIndicator.adaptive(), + ) + : Avatar( + client: Matrix.of(outerContext).client, + mxContent: profile.avatarUrl, + name: profile.name ?? roomAlias, + size: Avatar.defaultSize * 3, + ), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextButton.icon( + onPressed: roomLink != null + ? () => FluffyShare.share( + roomLink, + context, + copyOnly: true, + ) + : null, + icon: const Icon( + Icons.copy_outlined, + size: 14, + ), + style: TextButton.styleFrom( + foregroundColor: theme.colorScheme.onSurface, + ), + label: Text( + roomLink ?? '...', + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + TextButton.icon( + onPressed: () {}, + icon: const Icon( + Icons.groups_3_outlined, + size: 14, + ), + style: TextButton.styleFrom( + foregroundColor: theme.colorScheme.onSurface, + ), + label: Text( + L10n.of(context)!.countParticipants( + profile?.numJoinedMembers ?? 0, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], ), ), - ), + ], + ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: ElevatedButton.icon( onPressed: () => _joinRoom(context), label: Text( chunk?.joinRule == 'knock' && - Matrix.of(context) + Matrix.of(outerContext) .client .getRoomById(chunk!.roomId) == null @@ -157,36 +202,10 @@ class PublicRoomBottomSheet extends StatelessWidget { ? L10n.of(context)!.joinSpace : L10n.of(context)!.joinRoom, ), - icon: const Icon(Icons.login_outlined), + icon: const Icon(Icons.navigate_next), ), ), const SizedBox(height: 16), - ListTile( - title: Text( - profile?.name ?? - roomAlias?.localpart ?? - chunk?.roomId.localpart ?? - L10n.of(context)!.chat, - ), - subtitle: Text( - '${L10n.of(context)!.participant}: ${profile?.numJoinedMembers ?? 0}', - ), - trailing: const Icon(Icons.account_box_outlined), - ), - if (roomAlias != null) - ListTile( - title: Text(L10n.of(context)!.publicLink), - subtitle: SelectableText(roomAlias), - contentPadding: - const EdgeInsets.symmetric(horizontal: 16.0), - trailing: IconButton( - icon: const Icon(Icons.copy_outlined), - onPressed: () => FluffyShare.share( - roomAlias, - context, - ), - ), - ), if (profile?.topic?.isNotEmpty ?? false) ListTile( subtitle: SelectableLinkify( @@ -197,7 +216,7 @@ class PublicRoomBottomSheet extends StatelessWidget { ), style: TextStyle( fontSize: 14, - color: Theme.of(context).textTheme.bodyMedium!.color, + color: theme.textTheme.bodyMedium!.color, ), options: const LinkifyOptions(humanize: false), onOpen: (url) => diff --git a/lib/widgets/unread_rooms_badge.dart b/lib/widgets/unread_rooms_badge.dart index 9104b0f07..1e001de60 100644 --- a/lib/widgets/unread_rooms_badge.dart +++ b/lib/widgets/unread_rooms_badge.dart @@ -1,5 +1,4 @@ import 'package:badges/badges.dart' as b; -import 'package:fluffychat/utils/stream_extension.dart'; import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; @@ -19,54 +18,44 @@ class UnreadRoomsBadge extends StatelessWidget { @override Widget build(BuildContext context) { - return StreamBuilder( - stream: Matrix.of(context) - .client - .onSync - .stream - .where((syncUpdate) => syncUpdate.hasRoomUpdate) - // #Pangea - .rateLimit(const Duration(seconds: 1)), - // Pangea# - builder: (context, _) { - // #Pangea - // final unreadCount = Matrix.of(context) - // .client - // .rooms - // .where(filter) - // .where((r) => (r.isUnread || r.membership == Membership.invite)) - // .length; - final unreadCounts = Matrix.of(context) - .client - .rooms - .where(filter) - .where((r) => (r.isUnread || r.membership == Membership.invite)) - .map((r) => r.notificationCount); - final unreadCount = - unreadCounts.isEmpty ? 0 : unreadCounts.reduce((a, b) => a + b); - // Pangea# - return b.Badge( - badgeStyle: b.BadgeStyle( - badgeColor: Theme.of(context).colorScheme.primary, - elevation: 4, - borderSide: BorderSide( - color: Theme.of(context).colorScheme.surface, - width: 2, - ), - ), - badgeContent: Text( - unreadCount.toString(), - style: TextStyle( - color: Theme.of(context).colorScheme.onPrimary, - fontSize: 12, - ), - ), - showBadge: unreadCount != 0, - badgeAnimation: const b.BadgeAnimation.scale(), - position: badgePosition ?? b.BadgePosition.bottomEnd(), - child: child, - ); - }, + final theme = Theme.of(context); + + // #Pangea + // final unreadCount = Matrix.of(context) + // .client + // .rooms + // .where(filter) + // .where((r) => (r.isUnread || r.membership == Membership.invite)) + // .length; + final unreadCounts = Matrix.of(context) + .client + .rooms + .where(filter) + .where((r) => (r.isUnread || r.membership == Membership.invite)) + .map((r) => r.notificationCount); + final unreadCount = + unreadCounts.isEmpty ? 0 : unreadCounts.reduce((a, b) => a + b); + // Pangea# + return b.Badge( + badgeStyle: b.BadgeStyle( + badgeColor: theme.colorScheme.primary, + elevation: 4, + borderSide: BorderSide( + color: theme.colorScheme.surface, + width: 2, + ), + ), + badgeContent: Text( + unreadCount.toString(), + style: TextStyle( + color: theme.colorScheme.onPrimary, + fontSize: 12, + ), + ), + showBadge: unreadCount != 0, + badgeAnimation: const b.BadgeAnimation.scale(), + position: badgePosition ?? b.BadgePosition.bottomEnd(), + child: child, ); } } diff --git a/licenses.yaml b/licenses.yaml index 7b2f79bbf..ebab43440 100644 --- a/licenses.yaml +++ b/licenses.yaml @@ -12,6 +12,7 @@ permittedLicenses: - BSD-2-Clause - BSD-3-Clause - EUPL-1.2 + - LGPL-3.0 - MIT - MPL-2.0 - Zlib diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 0764f8001..99fe9d9d6 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) flutter_webrtc_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterWebRTCPlugin"); flutter_web_r_t_c_plugin_register_with_registrar(flutter_webrtc_registrar); + g_autoptr(FlPluginRegistrar) handy_window_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "HandyWindowPlugin"); + handy_window_plugin_register_with_registrar(handy_window_registrar); g_autoptr(FlPluginRegistrar) pasteboard_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "PasteboardPlugin"); pasteboard_plugin_register_with_registrar(pasteboard_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 92fe21eec..de98e488d 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_linux flutter_secure_storage_linux flutter_webrtc + handy_window pasteboard record_linux sentry_flutter diff --git a/linux/my_application.cc b/linux/my_application.cc index c185bcd78..7bddef81c 100644 --- a/linux/my_application.cc +++ b/linux/my_application.cc @@ -61,17 +61,17 @@ static void my_application_activate(GApplication* application) { } gtk_window_set_default_size(window, 864, 680); - gtk_widget_show(GTK_WIDGET(window)); g_autoptr(FlDartProject) project = fl_dart_project_new(); fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); FlView* view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + gtk_widget_show(GTK_WIDGET(window)); + gtk_widget_show(GTK_WIDGET(view)); gtk_widget_grab_focus(GTK_WIDGET(view)); } diff --git a/pubspec.lock b/pubspec.lock index e9e47cfb8..bb56964d1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -61,10 +61,10 @@ packages: dependency: "direct main" description: name: archive - sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "3.4.10" + version: "3.6.1" args: dependency: transitive description: @@ -85,10 +85,10 @@ packages: dependency: transitive description: name: audio_session - sha256: a49af9981eec5d7cd73b37bacb6ee73f8143a6a9f9bd5b6021e6c346b9b6cf4e + sha256: "4012d798e25a0ebfd4ad7203fefe7e386fdfedd2243afc52fa700b8bde6a3a4f" url: "https://pub.dev" source: hosted - version: "0.1.19" + version: "0.1.20" badges: dependency: "direct main" description: @@ -245,10 +245,10 @@ packages: dependency: transitive description: name: coverage - sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76" + sha256: "3945034e86ea203af7a056d98e98e42a5518fff200d6e8e6647e1886b07e936e" url: "https://pub.dev" source: hosted - version: "1.7.2" + version: "1.8.0" cross_file: dependency: transitive description: @@ -293,10 +293,10 @@ packages: dependency: transitive description: name: dart_webrtc - sha256: b3a4f109c551a10170ece8fc79b5ca1b98223f24bcebc0f971d7fe35daad7a3b + sha256: dc97a87e8d8c168fc5401ef18eaa0e06e1ac8fc099812de27a002860d021e227 url: "https://pub.dev" source: hosted - version: "1.4.4" + version: "1.4.7" dbus: dependency: transitive description: @@ -349,18 +349,10 @@ packages: dependency: "direct main" description: name: emoji_picker_flutter - sha256: "7c6681783e06710608df27be0e38aa4ba73ca1ccac370bb0e7a1320723ae4bca" + sha256: "839200a2bd1af9a65d71133a5a246dbf5b24f7e4f6f4c5390130c2e0ed5f85af" url: "https://pub.dev" source: hosted - version: "2.1.1" - emoji_proposal: - dependency: "direct main" - description: - name: emoji_proposal - sha256: e931bc42b54a65397b3df7915bb58ee7dcbd3ed81c3b8c256b9a5b210e94ea63 - url: "https://pub.dev" - source: hosted - version: "0.0.1" + version: "2.2.0" emojis: dependency: "direct main" description: @@ -420,10 +412,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "45c70b43df893027e441a6fa0aacc8f484fb9f9c60c746dc8f1dc4f774cf55cd" + sha256: "824f5b9f389bfc4dddac3dea76cd70c51092d9dff0b2ece7ef4f53db8547d258" url: "https://pub.dev" source: hosted - version: "8.0.2" + version: "8.0.6" file_selector_linux: dependency: transitive description: @@ -436,10 +428,10 @@ packages: dependency: transitive description: name: file_selector_macos - sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6 + sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 url: "https://pub.dev" source: hosted - version: "0.9.3+3" + version: "0.9.4" file_selector_platform_interface: dependency: transitive description: @@ -561,10 +553,10 @@ packages: dependency: "direct main" description: name: flutter_cache_manager - sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.4.1" flutter_dotenv: dependency: "direct main" description: @@ -582,10 +574,10 @@ packages: dependency: "direct main" description: name: flutter_foreground_task - sha256: d40a1ddd5f275450d2e32055e7f884796c028a02ac26c751c20916576f79e132 + sha256: "6cf10a27f5e344cd2ecad0752d3a5f4ec32846d82fda8753b3fe2480ebb832a3" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.5.0" flutter_highlighter: dependency: "direct main" description: @@ -662,10 +654,10 @@ packages: dependency: transitive description: name: flutter_layout_grid - sha256: "962a7ec8c7ea46c3b10606dac9c964f9143d10daa5ca28e40f4ce14eeef85b2a" + sha256: "88b4f8484a0874962e27c47733ad256aeb26acc694a9f029edbef771d301885a" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.0.7" flutter_linkify: dependency: "direct main" description: @@ -686,10 +678,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "40e6fbd2da7dcc7ed78432c5cdab1559674b4af035fddbfb2f9a8f9c2112fcef" + sha256: "0a9068149f0225e81642b03562e99776106edbd967816ee68bc16310d457c60e" url: "https://pub.dev" source: hosted - version: "17.1.2" + version: "17.2.1+1" flutter_local_notifications_linux: dependency: transitive description: @@ -702,10 +694,10 @@ packages: dependency: transitive description: name: flutter_local_notifications_platform_interface - sha256: "340abf67df238f7f0ef58f4a26d2a83e1ab74c77ab03cd2b2d5018ac64db30b7" + sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66" url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "7.2.0" flutter_localizations: dependency: "direct main" description: flutter @@ -715,10 +707,10 @@ packages: dependency: "direct main" description: name: flutter_map - sha256: cda8d72135b697f519287258b5294a57ce2f2a5ebf234f0e406aad4dc14c9399 + sha256: "87cc8349b8fa5dccda5af50018c7374b6645334a0d680931c1fe11bce88fa5bb" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.1" flutter_math_fork: dependency: "direct main" description: @@ -731,10 +723,10 @@ packages: dependency: "direct dev" description: name: flutter_native_splash - sha256: "9cdb5d9665dab5d098dc50feab74301c2c228cd02ca25c9b546ab572cebcd6af" + sha256: aa06fec78de2190f3db4319dd60fdc8d12b2626e93ef9828633928c2dcaea840 url: "https://pub.dev" source: hosted - version: "2.3.9" + version: "2.4.1" flutter_olm: dependency: "direct main" description: @@ -755,26 +747,26 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" + sha256: c6b0b4c05c458e1c01ad9bcc14041dd7b1f6783d487be4386f793f47a8a4d03e url: "https://pub.dev" source: hosted - version: "2.0.19" + version: "2.0.20" flutter_ringtone_player: dependency: "direct main" description: name: flutter_ringtone_player - sha256: bdbf0ba551fd81cf02fab5c45800dc0006fc51167a1ed252321046fd8ac2bce3 + sha256: d0277a04e629a6582d776f5dcc2a879a733f7326ba073b872a9ccfbff9d9b51f url: "https://pub.dev" source: hosted - version: "4.0.0+2" + version: "4.0.0+3" flutter_secure_storage: dependency: "direct main" description: name: flutter_secure_storage - sha256: ffdbb60130e4665d2af814a0267c481bcf522c41ae2e43caf69fa0146876d685 + sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0" url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "9.2.2" flutter_secure_storage_linux: dependency: "direct overridden" description: @@ -787,34 +779,34 @@ packages: dependency: transitive description: name: flutter_secure_storage_macos - sha256: bd33935b4b628abd0b86c8ca20655c5b36275c3a3f5194769a7b3f37c905369c + sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.2" flutter_secure_storage_platform_interface: dependency: transitive description: name: flutter_secure_storage_platform_interface - sha256: "0d4d3a5dd4db28c96ae414d7ba3b8422fd735a8255642774803b2532c9a61d7e" + sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.2" flutter_secure_storage_web: dependency: transitive description: name: flutter_secure_storage_web - sha256: "30f84f102df9dcdaa2241866a958c2ec976902ebdaa8883fbfe525f1f2f3cf20" + sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.1" flutter_secure_storage_windows: dependency: transitive description: name: flutter_secure_storage_windows - sha256: "5809c66f9dd3b4b93b0a6e2e8561539405322ee767ac2f64d084e2ab5429d108" + sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.1.2" flutter_shortcuts: dependency: "direct main" description: @@ -849,10 +841,10 @@ packages: dependency: "direct main" description: name: flutter_web_auth_2 - sha256: "3ea3a0cc539ca74319f4f2f7484f62742fe5b2ff9a0fca37575426d6e6f07901" + sha256: "4d3d2fd3d26bf1a26b3beafd4b4b899c0ffe10dc99af25abc58ffe24e991133c" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" flutter_web_auth_2_platform_interface: dependency: transitive description: @@ -870,26 +862,26 @@ packages: dependency: "direct main" description: name: flutter_webrtc - sha256: "63295f3aaba6e0e2520064a928fd0b79bf3636695af9c89cb219241994a45bf6" + sha256: fd5f115a08dcdc00b988bea3003c956f1b60a78a61d899cbddfb44f5d0e44d4a url: "https://pub.dev" source: hosted - version: "0.10.4" + version: "0.10.8" freezed_annotation: dependency: transitive description: name: freezed_annotation - sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.4" frontend_server_client: dependency: transitive description: name: frontend_server_client - sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "4.0.0" fuchsia_remote_debug_protocol: dependency: transitive description: flutter @@ -987,26 +979,34 @@ packages: dependency: "direct main" description: name: go_router - sha256: cdae1b9c8bd7efadcef6112e81c903662ef2ce105cbd220a04bbb7c3425b5554 + sha256: "39dd52168d6c59984454183148dc3a5776960c61083adfc708cc79a7b3ce1ba8" url: "https://pub.dev" source: hosted - version: "14.2.0" + version: "14.2.1" gradient_borders: dependency: transitive description: name: gradient_borders - sha256: "69eeaff519d145a4c6c213ada1abae386bcc8981a4970d923e478ce7ba19e309" + sha256: b1cd969552c83f458ff755aa68e13a0327d09f06c3f42f471b423b01427f21f8 url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" graphs: dependency: transitive description: name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" + handy_window: + dependency: "direct main" + description: + name: handy_window + sha256: "56b813e58a68b0ee2ab22051400b8b1f1b5cfe88b8cd32288623defb3926245a" + url: "https://pub.dev" + source: hosted + version: "0.4.0" highlighter: dependency: transitive description: @@ -1051,10 +1051,10 @@ packages: dependency: "direct main" description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_multi_server: dependency: transitive description: @@ -1075,26 +1075,26 @@ packages: dependency: "direct main" description: name: image - sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" url: "https://pub.dev" source: hosted - version: "4.1.7" + version: "4.2.0" image_picker: dependency: "direct main" description: name: image_picker - sha256: fe9ee64ccb8d599a5dfb0e21cc6652232c610bcf667af4e79b9eb175cc30a7a5 + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.2" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: "39f2bfe497e495450c81abcd44b62f56c2a36a37a175da7d137b4454977b51b1" + sha256: ff39a10ab4f48f4ac70776d0494a97bf073cd2570892cd46bc8a5cac162c25db url: "https://pub.dev" source: hosted - version: "0.8.9+3" + version: "0.8.12+4" image_picker_for_web: dependency: transitive description: @@ -1107,10 +1107,10 @@ packages: dependency: transitive description: name: image_picker_ios - sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 + sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447" url: "https://pub.dev" source: hosted - version: "0.8.9+1" + version: "0.8.12" image_picker_linux: dependency: transitive description: @@ -1248,26 +1248,26 @@ packages: dependency: "direct main" description: name: just_audio - sha256: b7cb6bbf3750caa924d03f432ba401ec300fd90936b3f73a9b33d58b1e96286b + sha256: ee50602364ba83fa6308f5512dd560c713ec3e1f2bc75f0db43618f0d82ef71a url: "https://pub.dev" source: hosted - version: "0.9.37" + version: "0.9.39" just_audio_platform_interface: dependency: transitive description: name: just_audio_platform_interface - sha256: c3dee0014248c97c91fe6299edb73dc4d6c6930a2f4f713579cd692d9e47f4a1 + sha256: "0243828cce503c8366cc2090cefb2b3c871aa8ed2f520670d76fd47aa1ab2790" url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.3.0" just_audio_web: dependency: transitive description: name: just_audio_web - sha256: "134356b0fe3d898293102b33b5fd618831ffdc72bb7a1b726140abdf22772b70" + sha256: "0edb481ad4aa1ff38f8c40f1a3576013c3420bf6669b686fe661627d49bc606c" url: "https://pub.dev" source: hosted - version: "0.4.9" + version: "0.4.11" jwt_decode: dependency: "direct main" description: @@ -1305,18 +1305,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -1369,10 +1369,10 @@ packages: dependency: transitive description: name: logger - sha256: "8c94b8c219e7e50194efc8771cd0e9f10807d8d3e219af473d89b06cc2ee4e04" + sha256: af05cc8714f356fd1f3888fb6741cbe9fbe25cdb6eedbab80e1a6db21047d4a4 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" logging: dependency: transitive description: @@ -1385,10 +1385,10 @@ packages: dependency: transitive description: name: macos_ui - sha256: d351f0bada7e5b0cee8cf394299878a6c04e5cfcd784fa1d40e44299501124d8 + sha256: "91c7f3427f763fd96b65831342b896b18751140e6bf55f8572fcb41f7b30bcab" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.7" macos_window_utils: dependency: transitive description: @@ -1417,35 +1417,35 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" material_symbols_icons: dependency: "direct main" description: name: material_symbols_icons - sha256: "36d4e5dd72f2fd282aca127cc4c4c29786d702cb506231ea73a5497fc324bf46" + sha256: b72bf7566d024d51627dce81b1b98539830a0e3ffbb5784989aa3e97c8493160 url: "https://pub.dev" source: hosted - version: "4.2741.0" + version: "4.2784.0" matrix: dependency: "direct main" description: path: "." ref: main - resolved-ref: "7c1349800b651edc451f2173388f26024a438bda" + resolved-ref: "3b77012ba93d6ff8f98dfdff00663aabeddf077e" url: "https://github.com/pangeachat/matrix-dart-sdk.git" source: git - version: "0.31.0" + version: "0.32.4" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" mgrs_dart: dependency: transitive description: @@ -1510,6 +1510,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.2" + opus_caf_converter_dart: + dependency: "direct main" + description: + name: opus_caf_converter_dart + sha256: e08156066916f790a54df305e103d6dec4d853ec23147e6a02eda3c06f67ba1a + url: "https://pub.dev" + source: hosted + version: "1.0.1" package_config: dependency: transitive description: @@ -1570,26 +1578,26 @@ packages: dependency: "direct main" description: name: path_provider - sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + sha256: "30c5aa827a6ae95ce2853cdc5fe3971daaac00f6f081c419c013f7f57bff2f5e" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.7" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" path_provider_linux: dependency: transitive description: @@ -1610,10 +1618,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.3.0" permission_handler: dependency: "direct main" description: @@ -1626,18 +1634,18 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: "758284a0976772f9c744d6384fc5dc4834aa61e3f7aa40492927f244767374eb" + sha256: a5ebaa420cee8fd880ef10dedd42c6b3f493e7dbe27d7e0a7e1798669373082a url: "https://pub.dev" source: hosted - version: "12.0.3" + version: "12.0.4" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: c6bf440f80acd2a873d3d91a699e4cc770f86e7e6b576dda98759e8b92b39830 + sha256: "6ca25ee52518a8a26e80aaefe3c71caf6e2dfd809c1b20900d0882df6faed36e" url: "https://pub.dev" source: hosted - version: "9.3.0" + version: "9.3.1" permission_handler_html: dependency: transitive description: @@ -1674,18 +1682,18 @@ packages: dependency: transitive description: name: platform - sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" platform_detect: dependency: transitive description: name: platform_detect - sha256: "08f4ee79c0e1c4858d37e06b22352a3ebdef5466b613749a3adb03e703d4f5b0" + sha256: a62f99417fc4fa2d099ce0ccdbb1bd3977920f2a64292c326271f049d4bc3a4f url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.1.0" plugin_platform_interface: dependency: transitive description: @@ -1698,18 +1706,18 @@ packages: dependency: transitive description: name: pointer_interceptor - sha256: bd18321519718678d5fa98ad3a3359cbc7a31f018554eab80b73d08a7f0c165a + sha256: d0a8e660d1204eaec5bd34b34cc92174690e076d2e4f893d9d68c486a13b07c4 url: "https://pub.dev" source: hosted - version: "0.10.1" + version: "0.10.1+1" pointer_interceptor_ios: dependency: transitive description: name: pointer_interceptor_ios - sha256: "2e73c39452830adc4695757130676a39412a3b7f3c34e3f752791b5384770877" + sha256: a6906772b3205b42c44614fcea28f818b1e5fdad73a4ca742a7bd49818d9c917 url: "https://pub.dev" source: hosted - version: "0.10.0+2" + version: "0.10.1" pointer_interceptor_platform_interface: dependency: transitive description: @@ -1726,14 +1734,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.10.2" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" - url: "https://pub.dev" - source: hosted - version: "3.7.4" polylabel: dependency: transitive description: @@ -1802,10 +1802,10 @@ packages: dependency: transitive description: name: pubspec_parse - sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 url: "https://pub.dev" source: hosted - version: "1.2.3" + version: "1.3.0" punycode: dependency: "direct main" description: @@ -1866,66 +1866,58 @@ packages: dependency: "direct main" description: name: record - sha256: "113b368168c49c78902ab37c2b354dea30a0aec5bdeca434073826b6ea73eca1" + sha256: "4a5cf4d083d1ee49e0878823c4397d073f8eb0a775f31215d388e2bc47a9e867" url: "https://pub.dev" source: hosted - version: "5.0.5" + version: "5.1.2" record_android: dependency: transitive description: name: record_android - sha256: "0df98e05873b22b443309e289bf1eb3b5b9a60e7779134334e2073eb0763a992" + sha256: "9ccf6a206dc72b486cf37893690e70c17610e8f05dba8da1a808e73dc2f49a04" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.4" record_darwin: dependency: transitive description: name: record_darwin - sha256: ee8cb1bb1712d7ce38140ecabe70e5c286c02f05296d66043bee865ace7eb1b9 + sha256: b038c26d1066eb81f4e7433bfb85f0d450ca3fac0002a7216b83a21b775ecf21 url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.1" record_linux: dependency: transitive description: name: record_linux - sha256: "7d0e70cd51635128fe9d37d89bafd6011d7cbba9af8dc323079ae60f23546aef" + sha256: "74d41a9ebb1eb498a38e9a813dd524e8f0b4fdd627270bda9756f437b110a3e3" url: "https://pub.dev" source: hosted - version: "0.7.1" + version: "0.7.2" record_platform_interface: dependency: transitive description: name: record_platform_interface - sha256: "3a4b56e94ecd2a0b2b43eb1fa6f94c5b8484334f5d38ef43959c4bf97fb374cf" + sha256: "11f8b03ea8a0e279b0e306571dbe0db0202c0b8e866495c9fa1ad2281d5e4c15" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" record_web: dependency: transitive description: name: record_web - sha256: "24847cdbcf999f7a5762170792f622ac844858766becd0f2370ec8ae22f7526e" + sha256: "703adb626d31e2dd86a8f6b34e306e03cd323e0c5e16e11bbc0385b07a8df97e" url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.1.1" record_windows: dependency: transitive description: name: record_windows - sha256: "39998b3ea7d8d28b04159d82220e6e5e32a7c357c6fb2794f5736beea272f6c3" + sha256: e653555aa3fda168aded7c34e11bd82baf0c6ac84e7624553def3c77ffefd36f url: "https://pub.dev" source: hosted - version: "1.0.2" - remove_emoji: - dependency: transitive - description: - name: remove_emoji - sha256: ed9e8463e8c9ca05b86fcddd4c0dbd2c2605a50d267f4ffa05496607924809e3 - url: "https://pub.dev" - source: hosted - version: "0.0.10" + version: "1.0.3" retry: dependency: transitive description: @@ -1982,22 +1974,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.2" - sentiment_dart: - dependency: transitive - description: - name: sentiment_dart - sha256: ddac8742cf5141f531eb1510b074ce715b9958cb02a763a4cc0a918768e4a0c8 - url: "https://pub.dev" - source: hosted - version: "0.0.5" sentry: dependency: transitive description: name: sentry - sha256: fd1fbfe860c05f5c52820ec4dbf2b6473789e83ead26cfc18bca4fe80bf3f008 + sha256: "1af8308298977259430d118ab25be8e1dda626cdefa1e6ce869073d530d39271" url: "https://pub.dev" source: hosted - version: "8.2.0" + version: "8.8.0" sentry_dart_plugin: dependency: "direct dev" description: @@ -2010,10 +1994,10 @@ packages: dependency: "direct main" description: name: sentry_flutter - sha256: c64f0aec5332bec87083b61514d1b6b29e435b9045d03ce1575861192b9a5680 + sha256: "18fe4d125c2d529bd6127200f0d2895768266a8c60b4fb50b2086fd97e1a4ab2" url: "https://pub.dev" source: hosted - version: "8.2.0" + version: "8.8.0" share_plus: dependency: "direct main" description: @@ -2042,18 +2026,18 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2" + sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" + sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" url: "https://pub.dev" source: hosted - version: "2.3.5" + version: "2.4.0" shared_preferences_linux: dependency: transitive description: @@ -2175,10 +2159,10 @@ packages: dependency: transitive description: name: sqflite - sha256: "5ce2e1a15e822c3b4bfb5400455775e421da7098eed8adc8f26298ada7c9308c" + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.3+1" sqflite_common: dependency: transitive description: @@ -2199,18 +2183,18 @@ packages: dependency: "direct main" description: name: sqlcipher_flutter_libs - sha256: "60fe3444ff5b1b298a9ca3003c6c7f1f7ee4c90aa6035a8647f3aeaf05a073e2" + sha256: "672e7f9d8a19896c3bfc44ca5f6fd8ee978970c5946817eeedf5e59c176aacf1" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.6.3" sqlite3: dependency: transitive description: name: sqlite3 - sha256: "1abbeb84bf2b1a10e5e1138c913123c8aa9d83cd64e5f9a0dd847b3c83063202" + sha256: "6d17989c0b06a5870b2190d391925186f944cb943e5262d0d3f778fcfca3bc6e" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.4" stack_trace: dependency: transitive description: @@ -2303,10 +2287,10 @@ packages: dependency: transitive description: name: tar - sha256: aca91e93ff9ff2dba4462c6eea6bc260b72f0d7010e748e3397c32190529bd6e + sha256: "22f67e2d77b51050436620b2a5de521c58ca6f0b75af1d9ab3c8cae2eae58fcd" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" term_glyph: dependency: transitive description: @@ -2319,34 +2303,34 @@ packages: dependency: transitive description: name: test - sha256: "7ee446762c2c50b3bd4ea96fe13ffac69919352bd3b4b17bac3f3465edc58073" + sha256: "7ee44229615f8f642b68120165ae4c2a75fe77ae2065b1e55ae4711f6cf0899e" url: "https://pub.dev" source: hosted - version: "1.25.2" + version: "1.25.7" test_api: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.2" test_core: dependency: transitive description: name: test_core - sha256: "2bc4b4ecddd75309300d8096f781c0e3280ca1ef85beda558d33fcbedc2eead4" + sha256: "55ea5a652e38a1dfb32943a7973f3681a60f872f8c3a05a14664ad54ef9c6696" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.4" timezone: dependency: transitive description: name: timezone - sha256: a6ccda4a69a442098b602c44e61a1e2b4bf6f5516e875bbf0f427d5df14745d5 + sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d" url: "https://pub.dev" source: hosted - version: "0.9.3" + version: "0.9.4" tint: dependency: transitive description: @@ -2471,26 +2455,26 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e" + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" url: "https://pub.dev" source: hosted - version: "6.2.6" + version: "6.3.0" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" + sha256: ceb2625f0c24ade6ef6778d1de0b2e44f2db71fded235eb52295247feba8c5cf url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.3" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.3.1" url_launcher_linux: dependency: transitive description: @@ -2503,10 +2487,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.2.0" url_launcher_platform_interface: dependency: transitive description: @@ -2535,10 +2519,10 @@ packages: dependency: transitive description: name: uuid - sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" + sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.4.2" vector_graphics: dependency: transitive description: @@ -2575,34 +2559,34 @@ packages: dependency: "direct main" description: name: video_compress - sha256: "407693726e674a1e1958801deb2d9daf5a5297707ba6d03375007012dae7389a" + sha256: "5b42d89f3970c956bad7a86c29682b0892c11a4ddf95ae6e29897ee28788e377" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" video_player: dependency: "direct main" description: name: video_player - sha256: db6a72d8f4fd155d0189845678f55ad2fd54b02c10dcafd11c068dbb631286c0 + sha256: e30df0d226c4ef82e2c150ebf6834b3522cf3f654d8e2f9419d376cdc071425d url: "https://pub.dev" source: hosted - version: "2.8.6" + version: "2.9.1" video_player_android: dependency: transitive description: name: video_player_android - sha256: "7f8f25d7ad56819a82b2948357f3c3af071f6a678db33833b26ec36bbc221316" + sha256: fdc0331ce9f808cc2714014cb8126bd6369943affefd54f8fdab0ea0bb617b7f url: "https://pub.dev" source: hosted - version: "2.4.11" + version: "2.5.2" video_player_avfoundation: dependency: transitive description: name: video_player_avfoundation - sha256: "309e3962795e761be010869bae65c0b0e45b5230c5cee1bec72197ca7db040ed" + sha256: d1e9a824f2b324000dc8fb2dcb2a3285b6c1c7c487521c63306cc5b394f68a7c url: "https://pub.dev" source: hosted - version: "2.5.6" + version: "2.6.1" video_player_platform_interface: dependency: transitive description: @@ -2615,10 +2599,10 @@ packages: dependency: transitive description: name: video_player_web - sha256: "34beb3a07d4331a24f7e7b2f75b8e2b103289038e07e65529699a671b6a6e2cb" + sha256: ff4d69a6614b03f055397c27a71c9d3ddea2b2a23d71b2ba0164f59ca32b8fe2 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.3.1" visibility_detector: dependency: transitive description: @@ -2631,10 +2615,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.2.5" wakelock_plus: dependency: "direct main" description: @@ -2700,13 +2684,13 @@ packages: source: hosted version: "1.2.0" win32: - dependency: transitive + dependency: "direct overridden" description: name: win32 - sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + sha256: "015002c060f1ae9f41a818f2d5640389cc05283e368be19dc8d77cecb43c40c9" url: "https://pub.dev" source: hosted - version: "5.5.0" + version: "5.5.3" win32_registry: dependency: transitive description: @@ -2756,5 +2740,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.0 <4.0.0" - flutter: ">=3.19.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index 95ea003b3..14dd3f54a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,7 @@ environment: dependencies: adaptive_dialog: ^2.1.0 animations: ^2.0.11 - archive: ^3.4.10 + archive: ^3.6.1 async: ^2.11.0 badges: ^3.1.2 blurhash_dart: ^1.2.1 @@ -29,20 +29,19 @@ dependencies: device_info_plus: ^10.0.1 dynamic_color: ^1.7.0 emoji_picker_flutter: ^2.1.1 - emoji_proposal: ^0.0.1 emojis: ^0.9.9 #fcm_shared_isolate: ^0.1.0 - file_picker: ^8.0.1 + file_picker: ^8.0.6 flutter: sdk: flutter flutter_app_badger: ^1.5.0 - flutter_cache_manager: ^3.3.1 + flutter_cache_manager: ^3.4.1 flutter_foreground_task: ^6.1.3 flutter_highlighter: ^0.1.1 flutter_html: ^3.0.0-beta.2 flutter_html_table: ^3.0.0-beta.2 flutter_linkify: ^6.0.0 - flutter_local_notifications: ^17.0.0 + flutter_local_notifications: ^17.2.1+1 flutter_localizations: sdk: flutter flutter_map: ^6.1.0 @@ -59,6 +58,7 @@ dependencies: future_loading_dialog: ^0.3.0 geolocator: ^7.6.2 go_router: ^14.0.1 + handy_window: ^0.4.0 hive: ^2.2.3 hive_flutter: ^1.1.0 html: ^0.15.4 @@ -66,15 +66,19 @@ dependencies: image: ^4.1.7 image_picker: ^1.1.0 intl: any - just_audio: ^0.9.37 + just_audio: ^0.9.39 keyboard_shortcuts: ^0.1.4 latlong2: ^0.9.1 linkify: ^5.0.0 + # #Pangea matrix: git: url: https://github.com/pangeachat/matrix-dart-sdk.git # repo ref: main # branch + # matrix: ^0.32.3 + # Pangea# native_imaging: ^0.1.1 + opus_caf_converter_dart: ^1.0.1 package_info_plus: ^6.0.0 pasteboard: ^0.2.0 path: ^1.9.0 @@ -85,7 +89,7 @@ dependencies: punycode: ^1.0.0 qr_code_scanner: ^1.0.1 receive_sharing_intent: 1.4.5 # Update needs more work - record: ^5.0.5 + record: ^5.1.2 scroll_to_index: ^3.0.1 share_plus: ^9.0.0 shared_preferences: ^2.2.0 # Pinned because https://github.com/flutter/flutter/issues/118401 @@ -98,7 +102,7 @@ dependencies: unifiedpush: ^5.0.1 universal_html: ^2.2.4 url_launcher: ^6.2.5 - video_compress: ^3.1.2 + video_compress: ^3.1.3 video_player: ^2.8.5 wakelock_plus: ^1.2.2 webrtc_interface: ^1.0.13 @@ -213,3 +217,4 @@ dependency_overrides: git: url: https://github.com/TheOneWithTheBraid/keyboard_shortcuts.git ref: null-safety + win32: 5.5.3 diff --git a/scripts/enable-android-google-services.patch b/scripts/enable-android-google-services.patch index 8353553d3..4ec4b8f13 100644 --- a/scripts/enable-android-google-services.patch +++ b/scripts/enable-android-google-services.patch @@ -1,32 +1,24 @@ diff --git a/android/app/build.gradle b/android/app/build.gradle -index bf972f30..46cebdc6 100644 +index 7520ff2a..ae376d9d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle -@@ -70,6 +70,10 @@ - } - release { - signingConfig signingConfigs.release -+ minifyEnabled false -+ shrinkResources false -+ -+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - // https://stackoverflow.com/a/77494454/8222484 -@@ -78,8 +82,11 @@ flutter { - - dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -- //implementation 'com.google.firebase:firebase-messaging:19.0.1' // Workaround for https://github.com/microg/android_packages_apps_GmsCore/issues/313#issuecomment-617651698 -+ implementation 'com.google.firebase:firebase-messaging:19.0.1' // Workaround for https://github.com/microg/android_packages_apps_GmsCore/issues/313#issuecomment-617651698 -+ testImplementation 'junit:junit:4.12' -+ androidTestImplementation 'androidx.test:runner:1.1.1' -+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' - implementation 'androidx.multidex:multidex:2.0.1' +@@ -2,7 +2,7 @@ plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +- //id "com.google.gms.google-services" ++ id "com.google.gms.google-services" } --//apply plugin: 'com.google.gms.google-services' -+apply plugin: 'com.google.gms.google-services' + def localProperties = new Properties() +@@ -83,6 +83,6 @@ flutter { + } + + dependencies { +- //implementation 'com.google.firebase:firebase-messaging:19.0.1' // Workaround for https://github.com/microg/android_packages_apps_GmsCore/issues/313#issuecomment-617651698 ++ implementation 'com.google.firebase:firebase-messaging:19.0.1' // Workaround for https://github.com/microg/android_packages_apps_GmsCore/issues/313#issuecomment-617651698 + implementation 'androidx.multidex:multidex:2.0.1' + } diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index d0e0fbc9..0a546da0 100644 --- a/android/app/proguard-rules.pro @@ -93,42 +85,25 @@ index d9930f55..510e9845 100644 } -*/ \ No newline at end of file -diff --git a/android/app/src/main/kotlin/chat/fluffy/fluffychat/MainActivity.kt b/android/app/src/main/kotlin/chat/fluffy/fluffychat/MainActivity.kt -index 1afc4606..894d1571 100644 ---- a/android/app/src/main/kotlin/chat/fluffy/fluffychat/MainActivity.kt -+++ b/android/app/src/main/kotlin/chat/fluffy/fluffychat/MainActivity.kt -@@ -7,13 +7,11 @@ import android.content.Context - import androidx.multidex.MultiDex - - class MainActivity : FlutterActivity() { -- - override fun attachBaseContext(base: Context) { - super.attachBaseContext(base) - MultiDex.install(this) - } - -- - override fun provideFlutterEngine(context: Context): FlutterEngine? { - return provideEngine(this) - } -diff --git a/android/build.gradle b/android/build.gradle -index bd394967..2e9d54de 100644 ---- a/android/build.gradle -+++ b/android/build.gradle -@@ -8,7 +8,7 @@ buildscript { - dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" -- //classpath 'com.google.gms:google-services:4.3.8' -+ classpath 'com.google.gms:google-services:4.3.8' - } +diff --git a/android/settings.gradle b/android/settings.gradle +index b2fd960a..fdb01a4d 100644 +--- a/android/settings.gradle ++++ b/android/settings.gradle +@@ -20,7 +20,7 @@ plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.1.2" apply false + id "org.jetbrains.kotlin.android" version "1.8.0" apply false +- // id "com.google.gms.google-services" version "4.3.8" apply false ++ id "com.google.gms.google-services" version "4.3.8" apply false } + include ":app" +\ No newline at end of file diff --git a/lib/utils/background_push.dart b/lib/utils/background_push.dart -index 8e67ae92..da4da5c3 100644 +index 039dde89..1cefdd71 100644 --- a/lib/utils/background_push.dart +++ b/lib/utils/background_push.dart -@@ -39,7 +39,7 @@ import '../config/setting_keys.dart'; +@@ -38,7 +38,7 @@ import '../config/setting_keys.dart'; import '../widgets/matrix.dart'; import 'platform_infos.dart'; @@ -137,7 +112,7 @@ index 8e67ae92..da4da5c3 100644 class NoTokenException implements Exception { String get cause => 'Cannot get firebase token'; -@@ -64,7 +64,7 @@ class BackgroundPush { +@@ -63,7 +63,7 @@ class BackgroundPush { final pendingTests = >{}; @@ -147,15 +122,15 @@ index 8e67ae92..da4da5c3 100644 DateTime? lastReceivedPush; diff --git a/pubspec.yaml b/pubspec.yaml -index 193e6ed6..f70e48d4 100644 +index 69c80d6e..efd32d89 100644 --- a/pubspec.yaml +++ b/pubspec.yaml -@@ -26,7 +26,7 @@ dependencies: +@@ -25,7 +25,7 @@ dependencies: + dynamic_color: ^1.7.0 emoji_picker_flutter: ^2.1.1 - emoji_proposal: ^0.0.1 emojis: ^0.9.9 - #fcm_shared_isolate: ^0.1.0 + fcm_shared_isolate: ^0.1.0 - file_picker: ^8.0.1 + file_picker: ^8.0.6 flutter: sdk: flutter diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index a32ad5704..63dfbb87d 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,6 +1,6 @@ name: fluffychat title: FluffyChat -base: core22 +base: core24 version: git license: AGPL-3.0 summary: The cutest messenger in the Matrix network @@ -44,9 +44,11 @@ description: | grade: stable confinement: strict -architectures: - - build-on: amd64 - - build-on: arm64 +platforms: + amd64: + build-on: amd64 + arm64: + build-on: arm64 parts: olm: @@ -64,40 +66,13 @@ parts: stage-snaps: - zenity-integration - flutter-git: - source: https://github.com/flutter/flutter.git - source-tag: 3.19.6 - source-depth: 1 - plugin: nil - override-build: | - mkdir -p $CRAFT_PART_INSTALL/usr/bin - mkdir -p $CRAFT_PART_INSTALL/usr/libexec - cp -r $CRAFT_PART_SRC $CRAFT_PART_INSTALL/usr/libexec/flutter - ln -s $CRAFT_PART_INSTALL/usr/libexec/flutter/bin/flutter $CRAFT_PART_INSTALL/usr/bin/flutter - ln -s $SNAPCRAFT_PART_INSTALL/usr/libexec/flutter/bin/dart $SNAPCRAFT_PART_INSTALL/usr/bin/dart - $CRAFT_PART_INSTALL/usr/bin/flutter doctor - build-packages: - - clang - - cmake - - curl - - libgtk-3-dev - - ninja-build - - unzip - - xz-utils - - zip - override-prime: '' - fluffychat: - after: [flutter-git] - plugin: nil + plugin: flutter source: . override-build: | # Workaround for Flutter build error: rm -rf build - - flutter build linux --release -v - mkdir -p $CRAFT_PART_INSTALL/bin/ - cp -r build/linux/*/release/bundle/* $CRAFT_PART_INSTALL/bin/ + craftctl default build-packages: - libjsoncpp-dev - curl @@ -114,7 +89,7 @@ slots: apps: fluffychat: - command: bin/fluffychat + command: fluffychat extensions: [ gnome ] plugs: - audio-playback